tokio/io/uring/
open.rs

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