Skip to main content

compio_driver/sys/op/
unix.rs

1//! OpCodes shared by both iour & polling driver
2
3use rustix::fs::*;
4
5use crate::op::*;
6
7/// Open or create a file with flags and mode.
8pub struct OpenFile<S: AsFd> {
9    pub(crate) dirfd: S,
10    pub(crate) path: CString,
11    pub(crate) flags: OFlags,
12    pub(crate) mode: Mode,
13    pub(crate) opened_fd: Option<OwnedFd>,
14}
15
16impl<S: AsFd> OpenFile<S> {
17    /// Create [`OpenFile`].
18    pub fn new(dirfd: S, path: CString, flags: OFlags, mode: Mode) -> Self {
19        Self {
20            dirfd,
21            path,
22            flags,
23            mode,
24            opened_fd: None,
25        }
26    }
27
28    pub(crate) fn call(&mut self, _: &mut ()) -> io::Result<usize> {
29        self.opened_fd = Some(openat(
30            self.dirfd.as_fd(),
31            &self.path,
32            self.flags | OFlags::CLOEXEC,
33            self.mode,
34        )?);
35        Ok(0)
36    }
37}
38
39impl<S: AsFd> IntoInner for OpenFile<S> {
40    type Inner = OwnedFd;
41
42    fn into_inner(self) -> Self::Inner {
43        self.opened_fd.expect("file not opened")
44    }
45}
46
47impl CloseFile {
48    pub(crate) fn call(&mut self, _: &mut ()) -> io::Result<usize> {
49        unsafe { ManuallyDrop::drop(&mut self.fd) };
50        Ok(0)
51    }
52}
53
54/// Truncates or extends the underlying file, updating the size of file `S` to
55/// `size`.
56#[derive(Debug)]
57pub struct TruncateFile<S: AsFd> {
58    pub(crate) fd: S,
59    pub(crate) size: u64,
60}
61
62impl<S: AsFd> TruncateFile<S> {
63    /// Create [`TruncateFile`].
64    pub fn new(fd: S, size: u64) -> Self {
65        Self { fd, size }
66    }
67
68    pub(crate) fn call(&self) -> io::Result<usize> {
69        ftruncate(self.fd.as_fd(), self.size)?;
70        Ok(0)
71    }
72}
73
74#[doc(hidden)]
75#[derive(Default)]
76pub struct VectoredControl {
77    pub(crate) slices: Vec<SysSlice>,
78}
79
80/// Read a file at specified position into vectored buffer.
81pub struct ReadVectoredAt<T: IoVectoredBufMut, S> {
82    pub(crate) fd: S,
83    pub(crate) offset: u64,
84    pub(crate) buffer: T,
85}
86
87impl<T: IoVectoredBufMut, S> ReadVectoredAt<T, S> {
88    /// Create [`ReadVectoredAt`].
89    pub fn new(fd: S, offset: u64, buffer: T) -> Self {
90        Self { fd, offset, buffer }
91    }
92}
93
94impl<T: IoVectoredBufMut, S> IntoInner for ReadVectoredAt<T, S> {
95    type Inner = T;
96
97    fn into_inner(self) -> Self::Inner {
98        self.buffer
99    }
100}
101
102/// Write a file at specified position from vectored buffer.
103pub struct WriteVectoredAt<T: IoVectoredBuf, S> {
104    pub(crate) fd: S,
105    pub(crate) offset: u64,
106    pub(crate) buffer: T,
107}
108
109impl<T: IoVectoredBuf, S> WriteVectoredAt<T, S> {
110    /// Create [`WriteVectoredAt`].
111    pub fn new(fd: S, offset: u64, buffer: T) -> Self {
112        Self { fd, offset, buffer }
113    }
114}
115
116impl<T: IoVectoredBuf, S> IntoInner for WriteVectoredAt<T, S> {
117    type Inner = T;
118
119    fn into_inner(self) -> Self::Inner {
120        self.buffer
121    }
122}
123
124/// Receive a file into vectored buffer.
125pub struct ReadVectored<T: IoVectoredBufMut, S> {
126    pub(crate) fd: S,
127    pub(crate) buffer: T,
128}
129
130impl<T: IoVectoredBufMut, S> ReadVectored<T, S> {
131    /// Create [`ReadVectored`].
132    pub fn new(fd: S, buffer: T) -> Self {
133        Self { fd, buffer }
134    }
135}
136
137impl<T: IoVectoredBufMut, S> IntoInner for ReadVectored<T, S> {
138    type Inner = T;
139
140    fn into_inner(self) -> Self::Inner {
141        self.buffer
142    }
143}
144
145/// Send to a file from vectored buffer.
146pub struct WriteVectored<T: IoVectoredBuf, S> {
147    pub(crate) fd: S,
148    pub(crate) buffer: T,
149}
150
151impl<T: IoVectoredBuf, S> WriteVectored<T, S> {
152    /// Create [`WriteVectored`].
153    pub fn new(fd: S, buffer: T) -> Self {
154        Self { fd, buffer }
155    }
156}
157
158impl<T: IoVectoredBuf, S> IntoInner for WriteVectored<T, S> {
159    type Inner = T;
160
161    fn into_inner(self) -> Self::Inner {
162        self.buffer
163    }
164}
165
166/// Remove file or directory.
167pub struct Unlink<S: AsFd> {
168    pub(crate) dirfd: S,
169    pub(crate) path: CString,
170    pub(crate) dir: bool,
171}
172
173impl<S: AsFd> Unlink<S> {
174    /// Create [`Unlink`].
175    pub fn new(dirfd: S, path: CString, dir: bool) -> Self {
176        Self { dirfd, path, dir }
177    }
178
179    pub(crate) fn call(&mut self, _: &mut ()) -> io::Result<usize> {
180        let flags = if self.dir {
181            AtFlags::REMOVEDIR
182        } else {
183            AtFlags::empty()
184        };
185
186        unlinkat(self.dirfd.as_fd(), &self.path, flags)?;
187
188        Ok(0)
189    }
190}
191
192/// Create a directory.
193pub struct CreateDir<S: AsFd> {
194    pub(crate) dirfd: S,
195    pub(crate) path: CString,
196    pub(crate) mode: Mode,
197}
198
199impl<S: AsFd> CreateDir<S> {
200    /// Create [`CreateDir`].
201    pub fn new(dirfd: S, path: CString, mode: Mode) -> Self {
202        Self { dirfd, path, mode }
203    }
204
205    pub(crate) fn call(&mut self, _: &mut ()) -> io::Result<usize> {
206        mkdirat(self.dirfd.as_fd(), &self.path, self.mode)?;
207
208        Ok(0)
209    }
210}
211
212/// Rename a file or directory.
213pub struct Rename<S1: AsFd, S2: AsFd> {
214    pub(crate) old_dirfd: S1,
215    pub(crate) old_path: CString,
216    pub(crate) new_dirfd: S2,
217    pub(crate) new_path: CString,
218}
219
220impl<S1: AsFd, S2: AsFd> Rename<S1, S2> {
221    /// Create [`Rename`].
222    pub fn new(old_dirfd: S1, old_path: CString, new_dirfd: S2, new_path: CString) -> Self {
223        Self {
224            old_dirfd,
225            old_path,
226            new_dirfd,
227            new_path,
228        }
229    }
230
231    pub(crate) fn call(&mut self, _: &mut ()) -> io::Result<usize> {
232        renameat(
233            self.old_dirfd.as_fd(),
234            &self.old_path,
235            self.new_dirfd.as_fd(),
236            &self.new_path,
237        )?;
238
239        Ok(0)
240    }
241}
242
243/// Create a symlink.
244pub struct Symlink<S: AsFd> {
245    pub(crate) source: CString,
246    pub(crate) dirfd: S,
247    pub(crate) target: CString,
248}
249
250impl<S: AsFd> Symlink<S> {
251    /// Create [`Symlink`]. `target` is a symlink to `source`.
252    pub fn new(source: CString, dirfd: S, target: CString) -> Self {
253        Self {
254            source,
255            dirfd,
256            target,
257        }
258    }
259
260    pub(crate) fn call(&mut self, _: &mut ()) -> io::Result<usize> {
261        symlinkat(&self.source, self.dirfd.as_fd(), &self.target)?;
262
263        Ok(0)
264    }
265}
266
267/// Create a hard link.
268pub struct HardLink<S1: AsFd, S2: AsFd> {
269    pub(crate) source_dirfd: S1,
270    pub(crate) source: CString,
271    pub(crate) target_dirfd: S2,
272    pub(crate) target: CString,
273}
274
275impl<S1: AsFd, S2: AsFd> HardLink<S1, S2> {
276    /// Create [`HardLink`]. `target` is a hard link to `source`.
277    pub fn new(source_dirfd: S1, source: CString, target_dirfd: S2, target: CString) -> Self {
278        Self {
279            source_dirfd,
280            source,
281            target_dirfd,
282            target,
283        }
284    }
285
286    pub(crate) fn call(&mut self, _: &mut ()) -> io::Result<usize> {
287        linkat(
288            self.source_dirfd.as_fd(),
289            &self.source,
290            self.target_dirfd.as_fd(),
291            &self.target,
292            AtFlags::empty(),
293        )?;
294        Ok(0)
295    }
296}
297
298/// Poll a file descriptor for specified [`Interest`].
299pub struct PollOnce<S> {
300    pub(crate) fd: S,
301    pub(crate) interest: Interest,
302}
303
304impl<S> PollOnce<S> {
305    /// Create [`PollOnce`].
306    pub fn new(fd: S, interest: Interest) -> Self {
307        Self { fd, interest }
308    }
309}
310
311impl<S> IntoInner for PollOnce<S> {
312    type Inner = S;
313
314    fn into_inner(self) -> Self::Inner {
315        self.fd
316    }
317}
318
319/// Create a pipe.
320pub struct Pipe {
321    pub(crate) fds: [Option<OwnedFd>; 2],
322}
323
324// Niche optimization.
325const _: () = assert!(std::mem::size_of::<Option<OwnedFd>>() == std::mem::size_of::<RawFd>());
326
327impl Pipe {
328    /// Create [`Pipe`].
329    #[allow(clippy::new_without_default)]
330    pub fn new() -> Self {
331        Self { fds: [None, None] }
332    }
333
334    pub(crate) fn call(&mut self) -> io::Result<usize> {
335        self.fds = mk_pipe()?;
336        Ok(0)
337    }
338}
339
340impl IntoInner for Pipe {
341    type Inner = (OwnedFd, OwnedFd);
342
343    fn into_inner(self) -> Self::Inner {
344        let [read_fd, write_fd] = self.fds;
345        let read_fd = read_fd.expect("pipe not created");
346        let write_fd = write_fd.expect("pipe not created");
347        (read_fd, write_fd)
348    }
349}