From: 小太 <nospam@kota.moe> This allows various disk benchmarking software like CrystalDiskMark and ATTO disk benchmark to actually benchmark the disk rather than the file cache Implementation based on public Microsoft NtCreateFile() documentation: https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntc... According to the documentation, Windows forbids FILE_APPEND_DATA and FILE_NO_INTERMEDIATE_BUFFERING being set together, but Linux has no such limitation with the equivalent O_APPEND and O_DIRECT... --- server/fd.c | 8 +++++++- server/file.c | 9 +++++++++ server/unicode.c | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/server/fd.c b/server/fd.c index f70bec354a3..ea11107bd1c 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1927,7 +1927,9 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam char *path; if (((options & FILE_DELETE_ON_CLOSE) && !(access & DELETE)) || - ((options & FILE_DIRECTORY_FILE) && (flags & O_TRUNC))) + ((options & FILE_DIRECTORY_FILE) && (flags & O_TRUNC)) || + ((options & FILE_SYNCHRONOUS_IO_ALERT) && !(access & SYNCHRONIZE)) || + ((options & FILE_SYNCHRONOUS_IO_NONALERT) && !(access & SYNCHRONIZE))) { set_error( STATUS_INVALID_PARAMETER ); return NULL; @@ -1974,6 +1976,10 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam } else rw_mode = O_RDONLY; + if (options & FILE_NO_INTERMEDIATE_BUFFERING) flags |= O_DIRECT; + if (options & FILE_SYNCHRONOUS_IO_NONALERT) flags |= O_SYNC; + if (options & FILE_SYNCHRONOUS_IO_ALERT) flags |= O_SYNC; + if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1) { /* if we tried to open a directory for write access, retry read-only */ diff --git a/server/file.c b/server/file.c index cc5acc2aadc..3f205bb7a8e 100644 --- a/server/file.c +++ b/server/file.c @@ -220,6 +220,15 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si char *name; mode_t mode; + if (((options & FILE_NO_INTERMEDIATE_BUFFERING) && (access & FILE_APPEND_DATA))) + { + /* map_access() below will set FILE_APPEND_DATA for any WRITE access, so + checking for this Windows-only error condition has to be done here + instead of in open_fd() */ + set_error( STATUS_INVALID_PARAMETER ); + return NULL; + } + if (!len || ((nameptr[0] == '/') ^ !root) || (nt_name.len && ((nt_name.str[0] == '\\') ^ !root))) { set_error( STATUS_OBJECT_PATH_SYNTAX_BAD ); diff --git a/server/unicode.c b/server/unicode.c index bb39b55e50c..630db4cfff8 100644 --- a/server/unicode.c +++ b/server/unicode.c @@ -343,7 +343,7 @@ struct fd *load_intl_file(void) { if (!nls_dirs[i]) continue; if (asprintf( &path, "%s/l_intl.nls", nls_dirs[i] ) == -1) continue; - if ((fd = open_fd( NULL, path, nt_name, O_RDONLY, &mode, FILE_READ_DATA, + if ((fd = open_fd( NULL, path, nt_name, O_RDONLY, &mode, FILE_READ_DATA | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) break; free( path ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9809