Implement __wasi_fd_fdstat_get for Windows.

This commit fully implements `__wasi_fd_fdstat_get` on Windows so that
the descriptor flags can be determined.

It does this by calling into `NtQueryInformationFile` (safe to call from
user mode) to get the open mode and access of the underlying OS handle.

`NtQueryInformationFile` isn't included in the `winapi` crate, so it is
manually being linked against.

This commit also fixes several bugs on Windows:

* Ignore `__WASI_FDFLAG_NONBLOCK` by not setting `FILE_FLAG_OVERLAPPED`
  on file handles (the POSIX behavior for `O_NONBLOCK` on files).
* Use `FILE_FLAG_WRITE_THROUGH` for the `__WASI_FDFLAG_?SYNC` flags.
* `__WASI_FDFLAG_APPEND` should disallow `FILE_WRITE_DATA` access to
  force append-only on write operations.
* Use `GENERIC_READ` and `GENERIC_WRITE` access flags.  The
  latter is required when opening a file for truncation.
This commit is contained in:
Peter Huene
2019-11-12 16:41:54 -08:00
committed by Jakub Konka
parent 3e7bc745a2
commit 0cf54ffeba
11 changed files with 245 additions and 172 deletions

View File

@@ -12,7 +12,6 @@ cfg_if! {
} else if #[cfg(windows)] {
mod windows;
pub(crate) use self::windows::*;
pub use self::windows::preopen_dir;
pub(crate) fn errno_from_host(err: i32) -> wasi::__wasi_errno_t {
host_impl::errno_from_win(winx::winerror::WinError::from_u32(err as u32))

View File

@@ -53,13 +53,13 @@ pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
wasi::__wasi_rights_t,
wasi::__wasi_rights_t,
)> {
use winx::file::{get_file_access_mode, AccessMode};
use winx::file::{query_access_information, AccessMode};
let (file_type, mut rights_base, rights_inheriting) = determine_type_rights(handle)?;
match file_type {
wasi::__WASI_FILETYPE_DIRECTORY | wasi::__WASI_FILETYPE_REGULAR_FILE => {
let mode = get_file_access_mode(handle.as_raw_handle())?;
let mode = query_access_information(handle.as_raw_handle())?;
if mode.contains(AccessMode::FILE_GENERIC_READ) {
rights_base |= wasi::__WASI_RIGHTS_FD_READ;
}

View File

@@ -56,7 +56,7 @@ pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: wasi::__wasi_filesize_t
pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
use winx::file::AccessMode;
unsafe { winx::file::get_file_access_mode(fd.as_raw_handle()) }
unsafe { winx::file::query_access_information(fd.as_raw_handle()) }
.map(host_impl::fdflags_from_win)
.map_err(Into::into)
}

View File

@@ -4,7 +4,6 @@ pub(crate) mod hostcalls_impl;
use crate::old::snapshot_0::Result;
use std::fs::{File, OpenOptions};
use std::path::Path;
pub(crate) fn dev_null() -> Result<File> {
OpenOptions::new()
@@ -13,20 +12,3 @@ pub(crate) fn dev_null() -> Result<File> {
.open("NUL")
.map_err(Into::into)
}
pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
use std::fs::OpenOptions;
use std::os::windows::fs::OpenOptionsExt;
use winapi::um::winbase::FILE_FLAG_BACKUP_SEMANTICS;
// To open a directory using CreateFile, specify the
// FILE_FLAG_BACKUP_SEMANTICS flag as part of dwFileFlags...
// cf. https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfile2
OpenOptions::new()
.create(false)
.write(true)
.read(true)
.attributes(FILE_FLAG_BACKUP_SEMANTICS)
.open(path)
.map_err(Into::into)
}