Skip to main content

tokio/io/uring/
open.rs

1use super::utils::cstr;
2
3use crate::fs::UringOpenOptions;
4use crate::runtime::driver::op::{CancelData, Cancellable, Completable, CqeResult, Op};
5
6use io_uring::{opcode, types};
7use std::ffi::CString;
8use std::io::{self, Error};
9use std::os::fd::FromRawFd;
10use std::path::Path;
11
12#[derive(Debug)]
13pub(crate) struct Open {
14    /// This field will be read by the kernel during the operation, so we
15    /// need to ensure it is valid for the entire duration of the operation.
16    #[allow(dead_code)]
17    path: CString,
18}
19
20impl Completable for Open {
21    type Output = io::Result<crate::fs::File>;
22    fn complete(self, cqe: CqeResult) -> Self::Output {
23        cqe.result
24            .map(|fd| unsafe { crate::fs::File::from_raw_fd(fd as i32) })
25    }
26
27    fn complete_with_error(self, err: Error) -> Self::Output {
28        Err(err)
29    }
30}
31
32impl Cancellable for Open {
33    fn cancel(self) -> CancelData {
34        CancelData::Open(self)
35    }
36}
37
38impl Op<Open> {
39    /// Submit a request to open a file.
40    pub(crate) fn open(path: &Path, options: &UringOpenOptions) -> io::Result<Op<Open>> {
41        let inner_opt = options;
42        let path = cstr(path)?;
43
44        let custom_flags = inner_opt.custom_flags;
45        let flags = libc::O_CLOEXEC
46            | options.access_mode()?
47            | options.creation_mode()?
48            | (custom_flags & !libc::O_ACCMODE);
49
50        let open_op = opcode::OpenAt::new(types::Fd(libc::AT_FDCWD), path.as_ptr())
51            .flags(flags)
52            .mode(inner_opt.mode)
53            .build();
54
55        // SAFETY: Parameters are valid for the entire duration of the operation
56        let op = unsafe { Op::new(open_op, Open { path }) };
57        Ok(op)
58    }
59}