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 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 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
101pub struct FileStat<S> {
103 pub(crate) fd: S,
104 pub(crate) stat: fs::Statx,
105}
106
107impl<S> FileStat<S> {
108 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
148pub 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 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}