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<T: IoBufMut> OpCode for GetXattr<T> {
45    type Control = ();
46
47    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
48        let slice = self.buffer.sys_slice_mut();
49        opcode::GetXattr::new(
50            self.name.as_ptr(),
51            slice.ptr().cast(),
52            self.path.as_ptr(),
53            slice.len().try_into().unwrap_or(u32::MAX),
54        )
55        .build()
56        .into()
57    }
58
59    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
60        self.call(control)
61    }
62}
63
64unsafe impl<S: AsFd, T: IoBufMut> OpCode for FGetXattr<S, T> {
65    type Control = ();
66
67    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
68        let slice = self.buffer.sys_slice_mut();
69        opcode::FGetXattr::new(
70            Fd(self.fd.as_fd().as_raw_fd()),
71            self.name.as_ptr(),
72            slice.ptr().cast(),
73            slice.len().try_into().unwrap_or(u32::MAX),
74        )
75        .build()
76        .into()
77    }
78
79    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
80        self.call(control)
81    }
82}
83
84unsafe impl<S: AsFd> OpCode for TruncateFile<S> {
85    type Control = ();
86
87    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
88        opcode::Ftruncate::new(Fd(self.fd.as_fd().as_raw_fd()), self.size)
89            .build()
90            .into()
91    }
92
93    fn call_blocking(&mut self, _: &mut Self::Control) -> io::Result<usize> {
94        self.call()
95    }
96}
97
98/// Get metadata of an opened file.
99pub struct FileStat<S> {
100    pub(crate) fd: S,
101    pub(crate) stat: fs::Statx,
102}
103
104impl<S> FileStat<S> {
105    /// Create [`FileStat`].
106    pub fn new(fd: S) -> Self {
107        Self {
108            fd,
109            stat: unsafe { std::mem::zeroed() },
110        }
111    }
112}
113
114unsafe impl<S: AsFd> OpCode for FileStat<S> {
115    type Control = ();
116
117    fn create_entry(&mut self, _control: &mut Self::Control) -> OpEntry {
118        static EMPTY_NAME: &[u8] = b"\0";
119        opcode::Statx::new(
120            Fd(self.fd.as_fd().as_fd().as_raw_fd()),
121            EMPTY_NAME.as_ptr().cast(),
122            &raw mut self.stat as _,
123        )
124        .flags(libc::AT_EMPTY_PATH)
125        .mask(STATX_MASK.bits())
126        .build()
127        .into()
128    }
129
130    fn call_blocking(&mut self, _control: &mut Self::Control) -> io::Result<usize> {
131        self.stat = pal::statx(self.fd.as_fd(), c"", false)?;
132
133        Ok(0)
134    }
135}
136
137impl<S> IntoInner for FileStat<S> {
138    type Inner = FileAttr;
139
140    fn into_inner(self) -> Self::Inner {
141        statx_to_attr(self.stat)
142    }
143}
144
145/// Get metadata from path.
146pub struct PathStat<S: AsFd> {
147    pub(crate) dirfd: S,
148    pub(crate) path: CString,
149    pub(crate) stat: fs::Statx,
150    pub(crate) follow_symlink: bool,
151}
152
153impl<S: AsFd> PathStat<S> {
154    /// Create [`PathStat`].
155    pub fn new(dirfd: S, path: CString, follow_symlink: bool) -> Self {
156        Self {
157            dirfd,
158            path,
159            stat: unsafe { std::mem::zeroed() },
160            follow_symlink,
161        }
162    }
163}
164
165unsafe impl<S: AsFd> OpCode for PathStat<S> {
166    type Control = ();
167
168    fn create_entry(&mut self, _control: &mut Self::Control) -> OpEntry {
169        let mut flags = libc::AT_EMPTY_PATH;
170        if !self.follow_symlink {
171            flags |= libc::AT_SYMLINK_NOFOLLOW;
172        }
173        opcode::Statx::new(
174            Fd(self.dirfd.as_fd().as_raw_fd()),
175            self.path.as_ptr(),
176            &raw mut self.stat as _,
177        )
178        .flags(flags)
179        .mask(STATX_MASK.bits())
180        .build()
181        .into()
182    }
183
184    fn call_blocking(&mut self, _control: &mut Self::Control) -> io::Result<usize> {
185        self.stat = statx(self.dirfd.as_fd(), &self.path, self.follow_symlink)?;
186
187        Ok(0)
188    }
189}
190
191impl<S: AsFd> IntoInner for PathStat<S> {
192    type Inner = FileAttr;
193
194    fn into_inner(self) -> Self::Inner {
195        statx_to_attr(self.stat)
196    }
197}
198
199unsafe impl<S: AsFd> OpCode for Sync<S> {
200    type Control = ();
201
202    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
203        opcode::Fsync::new(Fd(self.fd.as_fd().as_raw_fd()))
204            .flags(if self.datasync {
205                FsyncFlags::DATASYNC
206            } else {
207                FsyncFlags::empty()
208            })
209            .build()
210            .into()
211    }
212}
213
214unsafe impl<S: AsFd> OpCode for Unlink<S> {
215    type Control = ();
216
217    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
218        opcode::UnlinkAt::new(Fd(self.dirfd.as_fd().as_raw_fd()), self.path.as_ptr())
219            .flags(if self.dir { libc::AT_REMOVEDIR } else { 0 })
220            .build()
221            .into()
222    }
223
224    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
225        self.call(control)
226    }
227}
228
229unsafe impl<S: AsFd> OpCode for CreateDir<S> {
230    type Control = ();
231
232    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
233        opcode::MkDirAt::new(Fd(self.dirfd.as_fd().as_raw_fd()), self.path.as_ptr())
234            .mode(self.mode.bits())
235            .build()
236            .into()
237    }
238
239    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
240        self.call(control)
241    }
242}
243
244unsafe impl<S1: AsFd, S2: AsFd> OpCode for Rename<S1, S2> {
245    type Control = ();
246
247    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
248        opcode::RenameAt::new(
249            Fd(self.old_dirfd.as_fd().as_raw_fd()),
250            self.old_path.as_ptr(),
251            Fd(self.new_dirfd.as_fd().as_raw_fd()),
252            self.new_path.as_ptr(),
253        )
254        .build()
255        .into()
256    }
257
258    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
259        self.call(control)
260    }
261}
262
263unsafe impl<S: AsFd> OpCode for Symlink<S> {
264    type Control = ();
265
266    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
267        opcode::SymlinkAt::new(
268            Fd(self.dirfd.as_fd().as_raw_fd()),
269            self.source.as_ptr(),
270            self.target.as_ptr(),
271        )
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}
280
281unsafe impl<S1: AsFd, S2: AsFd> OpCode for HardLink<S1, S2> {
282    type Control = ();
283
284    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
285        opcode::LinkAt::new(
286            Fd(self.source_dirfd.as_fd().as_raw_fd()),
287            self.source.as_ptr(),
288            Fd(self.target_dirfd.as_fd().as_raw_fd()),
289            self.target.as_ptr(),
290        )
291        .build()
292        .into()
293    }
294
295    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
296        self.call(control)
297    }
298}
299
300unsafe impl<S1: AsFd, S2: AsFd> OpCode for Splice<S1, S2> {
301    type Control = ();
302
303    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
304        opcode::Splice::new(
305            Fd(self.fd_in.as_fd().as_raw_fd()),
306            self.offset_in,
307            Fd(self.fd_out.as_fd().as_raw_fd()),
308            self.offset_out,
309            self.len.try_into().unwrap_or(u32::MAX),
310        )
311        .flags(self.flags.bits())
312        .build()
313        .into()
314    }
315
316    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
317        self.call(control)
318    }
319}