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