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