summaryrefslogtreecommitdiff
path: root/monoio
diff options
context:
space:
mode:
authorJin Wei Tan <[email protected]>2023-07-11 11:03:33 +0800
committerGitHub <[email protected]>2023-07-11 11:03:33 +0800
commitf891b7058158e2687a4c827e89fc6fda71d57793 (patch)
treea024f8cbc1c5c7cb4c6c8448645a5536ef124a08 /monoio
parente22989c352ee30560e50924617a776ab271a6282 (diff)
implement open op on windows (#189)
Diffstat (limited to 'monoio')
-rw-r--r--monoio/src/driver/op/open.rs42
-rw-r--r--monoio/src/fs/file.rs2
-rw-r--r--monoio/src/fs/open_options.rs94
3 files changed, 132 insertions, 6 deletions
diff --git a/monoio/src/driver/op/open.rs b/monoio/src/driver/op/open.rs
index a104678..a9b158b 100644
--- a/monoio/src/driver/op/open.rs
+++ b/monoio/src/driver/op/open.rs
@@ -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> {
@@ -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 {
@@ -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
}
@@ -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
+ )
+ }
}
diff --git a/monoio/src/fs/file.rs b/monoio/src/fs/file.rs
index 3fe9942..f7fa13c 100644
--- a/monoio/src/fs/file.rs
+++ b/monoio/src/fs/file.rs
@@ -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.
@@ -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,
diff --git a/monoio/src/fs/open_options.rs b/monoio/src/fs/open_options.rs
index 913e88c..cabd3a8 100644
--- a/monoio/src/fs/open_options.rs
+++ b/monoio/src/fs/open_options.rs
@@ -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},
@@ -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 {
@@ -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(),
}
}
@@ -264,7 +301,6 @@ impl OpenOptions {
self
}
- #[cfg(unix)]
/// Opens a file at `path` with the options specified by `self`.
///
/// # Errors
@@ -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),
@@ -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) => {}
@@ -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)]