Skip to content

Commit

Permalink
implement open op on windows (#189)
Browse files Browse the repository at this point in the history
  • Loading branch information
CarrotzRule123 authored Jul 11, 2023
1 parent e22989c commit f891b70
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 6 deletions.
42 changes: 40 additions & 2 deletions monoio/src/driver/op/open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,27 @@ use std::{ffi::CString, io, path::Path};

#[cfg(all(target_os = "linux", feature = "iouring"))]
use io_uring::{opcode, types};
#[cfg(windows)]
use windows_sys::Win32::{Foundation::INVALID_HANDLE_VALUE, Storage::FileSystem::CreateFileW};

use super::{Op, OpAble};
#[cfg(feature = "legacy")]
use crate::driver::legacy::ready::Direction;
#[cfg(windows)]
use crate::syscall;
#[cfg(all(unix, feature = "legacy"))]
use crate::{driver::legacy::ready::Direction, syscall_u32};
use crate::syscall_u32;
use crate::{driver::util::cstr, fs::OpenOptions};

/// Open a file
pub(crate) struct Open {
pub(crate) path: CString,
#[cfg(unix)]
flags: i32,
#[cfg(unix)]
mode: libc::mode_t,
#[cfg(windows)]
opts: OpenOptions,
}

impl Op<Open> {
Expand All @@ -30,6 +39,18 @@ impl Op<Open> {

Op::submit_with(Open { path, flags, mode })
}

#[cfg(windows)]
/// Submit a request to open a file.
pub(crate) fn open<P: AsRef<Path>>(path: P, options: &OpenOptions) -> io::Result<Op<Open>> {
// Here the path will be copied, so its safe.
let path = cstr(path.as_ref())?;

Op::submit_with(Open {
path,
opts: options.clone(),
})
}
}

impl OpAble for Open {
Expand All @@ -41,7 +62,7 @@ impl OpAble for Open {
.build()
}

#[cfg(all(unix, feature = "legacy"))]
#[cfg(feature = "legacy")]
fn legacy_interest(&self) -> Option<(Direction, usize)> {
None
}
Expand All @@ -54,4 +75,21 @@ impl OpAble for Open {
self.mode as libc::c_int
))
}

#[cfg(windows)]
fn legacy_call(&mut self) -> io::Result<u32> {
syscall!(
CreateFileW(
self.path.as_c_str().as_ptr(),
self.opts.access_mode()?,
self.opts.share_mode,
self.opts.security_attributes,
self.opts.creation_mode()?,
self.opts.get_flags_and_attributes(),
std::ptr::null_mut(),
),
PartialEq::eq,
INVALID_HANDLE_VALUE
)
}
}
2 changes: 0 additions & 2 deletions monoio/src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ pub struct File {
}

impl File {
#[cfg(unix)]
/// Attempts to open a file in read-only mode.
///
/// See the [`OpenOptions::open`] method for more details.
Expand Down Expand Up @@ -87,7 +86,6 @@ impl File {
OpenOptions::new().read(true).open(path).await
}

#[cfg(unix)]
/// Opens a file in write-only mode.
///
/// This function will create a file if it does not exist,
Expand Down
94 changes: 92 additions & 2 deletions monoio/src/fs/open_options.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
use std::{io, os::unix::prelude::OpenOptionsExt, path::Path};
#[cfg(unix)]
use std::os::unix::prelude::OpenOptionsExt;
use std::{io, path::Path};

#[cfg(windows)]
use windows_sys::Win32::{
Foundation::{ERROR_INVALID_PARAMETER, GENERIC_READ, GENERIC_WRITE},
Security::SECURITY_ATTRIBUTES,
Storage::FileSystem::{
CREATE_ALWAYS, CREATE_NEW, FILE_FLAG_OPEN_REPARSE_POINT, FILE_GENERIC_WRITE,
FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_WRITE_DATA, OPEN_ALWAYS,
OPEN_EXISTING, TRUNCATE_EXISTING,
},
};

use crate::{
driver::{op::Op, shared_fd::SharedFd},
Expand Down Expand Up @@ -61,6 +74,18 @@ pub struct OpenOptions {
pub(crate) mode: libc::mode_t,
#[cfg(unix)]
pub(crate) custom_flags: libc::c_int,
#[cfg(windows)]
pub(crate) custom_flags: u32,
#[cfg(windows)]
pub(crate) access_mode: Option<u32>,
#[cfg(windows)]
pub(crate) attributes: u32,
#[cfg(windows)]
pub(crate) share_mode: u32,
#[cfg(windows)]
pub(crate) security_qos_flags: u32,
#[cfg(windows)]
pub(crate) security_attributes: *mut SECURITY_ATTRIBUTES,
}

impl OpenOptions {
Expand Down Expand Up @@ -93,6 +118,18 @@ impl OpenOptions {
mode: 0o666,
#[cfg(unix)]
custom_flags: 0,
#[cfg(windows)]
custom_flags: 0,
#[cfg(windows)]
access_mode: None,
#[cfg(windows)]
share_mode: FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
#[cfg(windows)]
attributes: 0,
#[cfg(windows)]
security_qos_flags: 0,
#[cfg(windows)]
security_attributes: std::ptr::null_mut(),
}
}

Expand Down Expand Up @@ -264,7 +301,6 @@ impl OpenOptions {
self
}

#[cfg(unix)]
/// Opens a file at `path` with the options specified by `self`.
///
/// # Errors
Expand Down Expand Up @@ -320,6 +356,7 @@ impl OpenOptions {
)))
}

#[cfg(unix)]
pub(crate) fn access_mode(&self) -> io::Result<libc::c_int> {
match (self.read, self.write, self.append) {
(true, false, false) => Ok(libc::O_RDONLY),
Expand All @@ -331,6 +368,22 @@ impl OpenOptions {
}
}

#[cfg(windows)]
pub(crate) fn access_mode(&self) -> io::Result<u32> {
match (self.read, self.write, self.append, self.access_mode) {
(.., Some(mode)) => Ok(mode),
(true, false, false, None) => Ok(GENERIC_READ),
(false, true, false, None) => Ok(GENERIC_WRITE),
(true, true, false, None) => Ok(GENERIC_READ | GENERIC_WRITE),
(false, _, true, None) => Ok(FILE_GENERIC_WRITE & !FILE_WRITE_DATA),
(true, _, true, None) => Ok(GENERIC_READ | (FILE_GENERIC_WRITE & !FILE_WRITE_DATA)),
(false, false, false, None) => {
Err(io::Error::from_raw_os_error(ERROR_INVALID_PARAMETER))
}
}
}

#[cfg(unix)]
pub(crate) fn creation_mode(&self) -> io::Result<libc::c_int> {
match (self.write, self.append) {
(true, false) => {}
Expand All @@ -354,6 +407,43 @@ impl OpenOptions {
(_, _, true) => libc::O_CREAT | libc::O_EXCL,
})
}

#[cfg(windows)]
pub(crate) fn creation_mode(&self) -> io::Result<u32> {
match (self.write, self.append) {
(true, false) => {}
(false, false) => {
if self.truncate || self.create || self.create_new {
return Err(io::Error::from_raw_os_error(ERROR_INVALID_PARAMETER));
}
}
(_, true) => {
if self.truncate && !self.create_new {
return Err(io::Error::from_raw_os_error(ERROR_INVALID_PARAMETER));
}
}
}

Ok(match (self.create, self.truncate, self.create_new) {
(false, false, false) => OPEN_EXISTING,
(true, false, false) => OPEN_ALWAYS,
(false, true, false) => TRUNCATE_EXISTING,
(true, true, false) => CREATE_ALWAYS,
(_, _, true) => CREATE_NEW,
})
}

#[cfg(windows)]
pub(crate) fn get_flags_and_attributes(&self) -> u32 {
self.custom_flags
| self.attributes
| self.security_qos_flags
| if self.create_new {
FILE_FLAG_OPEN_REPARSE_POINT
} else {
0
}
}
}

#[cfg(unix)]
Expand Down

0 comments on commit f891b70

Please sign in to comment.