From: Qian Hong qhong@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com ---
dlls/ntdll/tests/file.c | 93 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index b7b46365911..5d234114fd5 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -2960,12 +2960,13 @@ static void test_file_disposition_information(void) { char tmp_path[MAX_PATH], buffer[MAX_PATH + 16]; DWORD dirpos; - HANDLE handle, handle2, handle3; + HANDLE handle, handle2, handle3, mapping; NTSTATUS res; IO_STATUS_BLOCK io; FILE_DISPOSITION_INFORMATION fdi; BOOL fileDeleted; - DWORD fdi2; + DWORD fdi2, size; + void *view;
GetTempPathA( MAX_PATH, tmp_path );
@@ -3312,6 +3313,94 @@ todo_wine ok( !fileDeleted, "Directory shouldn't have been deleted\n" ); fileDeleted = RemoveDirectoryA( buffer ); ok( fileDeleted, "Directory should have been deleted\n" ); + + /* a file with an open mapping handle cannot be deleted */ + + GetTempFileNameA( tmp_path, "dis", 0, buffer ); + handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 ); + ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError() ); + WriteFile(handle, "data", 4, &size, NULL); + mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL ); + ok( !!mapping, "failed to create mapping, error %u\n", GetLastError() ); + + fdi.DoDeleteFile = FALSE; + res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation ); + ok( !res, "got %#x\n", res ); + + fdi.DoDeleteFile = TRUE; + res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation ); + todo_wine ok( res == STATUS_CANNOT_DELETE, "got %#x\n", res ); + res = GetFileAttributesA( buffer ); + ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" ); + + CloseHandle( mapping ); + CloseHandle( handle ); + res = DeleteFileA( buffer ); + todo_wine ok( res, "got error %u\n", GetLastError() ); + + GetTempFileNameA( tmp_path, "dis", 0, buffer ); + handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 ); + ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError() ); + WriteFile(handle, "data", 4, &size, NULL); + mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL ); + ok( !!mapping, "failed to create mapping, error %u\n", GetLastError() ); + CloseHandle( mapping ); + + fdi.DoDeleteFile = TRUE; + res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation ); + ok( !res, "got %#x\n", res ); + + CloseHandle( handle ); + res = DeleteFileA( buffer ); + ok( !res, "expected failure\n" ); + ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %u\n", GetLastError() ); + + /* a file with an open view cannot be deleted */ + + GetTempFileNameA( tmp_path, "dis", 0, buffer ); + handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 ); + ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError() ); + WriteFile(handle, "data", 4, &size, NULL); + mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL ); + ok( !!mapping, "failed to create mapping, error %u\n", GetLastError() ); + view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4 ); + ok( !!view, "failed to map view, error %u\n", GetLastError() ); + CloseHandle( mapping ); + + fdi.DoDeleteFile = FALSE; + res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation ); + ok( !res, "got %#x\n", res ); + + fdi.DoDeleteFile = TRUE; + res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation ); + todo_wine ok( res == STATUS_CANNOT_DELETE, "got %#x\n", res ); + res = GetFileAttributesA( buffer ); + ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" ); + + UnmapViewOfFile( view ); + CloseHandle( handle ); + res = DeleteFileA( buffer ); + todo_wine ok( res, "got error %u\n", GetLastError() ); + + GetTempFileNameA( tmp_path, "dis", 0, buffer ); + handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 ); + ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError() ); + WriteFile(handle, "data", 4, &size, NULL); + mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL ); + ok( !!mapping, "failed to create mapping, error %u\n", GetLastError() ); + view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4 ); + ok( !!view, "failed to map view, error %u\n", GetLastError() ); + CloseHandle( mapping ); + UnmapViewOfFile( view ); + + fdi.DoDeleteFile = TRUE; + res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation ); + ok( !res, "got %#x\n", res ); + + CloseHandle( handle ); + res = DeleteFileA( buffer ); + ok( !res, "expected failure\n" ); + ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %u\n", GetLastError() ); }
static void test_file_name_information(void)
From: Qian Hong qhong@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- This patch had a corresponding entry in the old wine-staging bug tracker (bug 228), but unfortunately I could not find the contents of the bug. However, since it fixes existing functionality rather than introducing new functionality, I think it's worth submitting.
dlls/ntdll/tests/file.c | 8 ++++---- server/fd.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 5d234114fd5..19ae5f2ac21 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -3329,14 +3329,14 @@ todo_wine
fdi.DoDeleteFile = TRUE; res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation ); - todo_wine ok( res == STATUS_CANNOT_DELETE, "got %#x\n", res ); + ok( res == STATUS_CANNOT_DELETE, "got %#x\n", res ); res = GetFileAttributesA( buffer ); ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" );
CloseHandle( mapping ); CloseHandle( handle ); res = DeleteFileA( buffer ); - todo_wine ok( res, "got error %u\n", GetLastError() ); + ok( res, "got error %u\n", GetLastError() );
GetTempFileNameA( tmp_path, "dis", 0, buffer ); handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 ); @@ -3373,14 +3373,14 @@ todo_wine
fdi.DoDeleteFile = TRUE; res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation ); - todo_wine ok( res == STATUS_CANNOT_DELETE, "got %#x\n", res ); + ok( res == STATUS_CANNOT_DELETE, "got %#x\n", res ); res = GetFileAttributesA( buffer ); ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" );
UnmapViewOfFile( view ); CloseHandle( handle ); res = DeleteFileA( buffer ); - todo_wine ok( res, "got error %u\n", GetLastError() ); + ok( res, "got error %u\n", GetLastError() );
GetTempFileNameA( tmp_path, "dis", 0, buffer ); handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 ); diff --git a/server/fd.c b/server/fd.c index bfa2805d82b..e326354d127 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2452,6 +2452,17 @@ static void set_fd_disposition( struct fd *fd, int unlink )
if (unlink) { + struct fd *fd_ptr; + + LIST_FOR_EACH_ENTRY( fd_ptr, &fd->inode->open, struct fd, inode_entry ) + { + if (fd_ptr->access & FILE_MAPPING_ACCESS) + { + set_error( STATUS_CANNOT_DELETE ); + return; + } + } + if (fstat( fd->unix_fd, &st ) == -1) { file_set_error();
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/kernel32/tests/file.c | 186 +++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 138f1e6c2d3..c09438e09bd 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -5924,6 +5924,191 @@ static void test_move_file(void) SetCurrentDirectoryA( cwd ); }
+static void test_eof(void) +{ + char temp_path[MAX_PATH], filename[MAX_PATH], buffer[20]; + LARGE_INTEGER file_size; + HANDLE file, mapping; + unsigned int i; + void *view; + DWORD size; + BOOL ret; + + static const struct + { + DWORD protection; + DWORD view_access; + } + map_tests[] = + { + {PAGE_READONLY, FILE_MAP_READ}, + {PAGE_READWRITE, FILE_MAP_WRITE}, + }; + + GetTempPathA(sizeof(temp_path), temp_path); + GetTempFileNameA(temp_path, "eof", 0, filename); + + file = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0); + ok(file != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError()); + + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(!file_size.QuadPart, "got size %I64d\n", file_size.QuadPart); + + SetFilePointer(file, 2, NULL, SEEK_SET); + + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(!file_size.QuadPart, "got size %I64d\n", file_size.QuadPart); + + ret = ReadFile(file, buffer, sizeof(buffer), &size, NULL); + ok(ret, "failed to read, error %u\n", GetLastError()); + ok(!size, "got size %u\n", size); + + ret = SetEndOfFile(file); + ok(ret, "failed to set EOF, error %u\n", GetLastError()); + + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 2, "got size %I64d\n", file_size.QuadPart); + + ret = WriteFile(file, "data", 4, &size, NULL); + ok(ret, "failed to write, error %u\n", GetLastError()); + ok(size == 4, "got size %u\n", size); + + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 6, "got size %I64d\n", file_size.QuadPart); + + SetFilePointer(file, 4, NULL, SEEK_SET); + ret = SetEndOfFile(file); + ok(ret, "failed to set EOF, error %u\n", GetLastError()); + + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 4, "got size %I64d\n", file_size.QuadPart); + + SetFilePointer(file, 0, NULL, SEEK_SET); + ret = ReadFile(file, buffer, sizeof(buffer), &size, NULL); + ok(ret, "failed to read, error %u\n", GetLastError()); + ok(size == 4, "got size %u\n", size); + ok(!memcmp(buffer, "\0\0da", 4), "wrong data\n"); + + SetFilePointer(file, 6, NULL, SEEK_SET); + ret = SetEndOfFile(file); + ok(ret, "failed to set EOF, error %u\n", GetLastError()); + + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 6, "got size %I64d\n", file_size.QuadPart); + + SetFilePointer(file, 0, NULL, SEEK_SET); + ret = ReadFile(file, buffer, sizeof(buffer), &size, NULL); + ok(ret, "failed to read, error %u\n", GetLastError()); + ok(size == 6, "got size %u\n", size); + ok(!memcmp(buffer, "\0\0da\0\0", 6), "wrong data\n"); + + ret = SetEndOfFile(file); + ok(ret, "failed to set EOF, error %u\n", GetLastError()); + + SetFilePointer(file, 2, NULL, SEEK_SET); + ret = WriteFile(file, "data", 4, &size, NULL); + ok(ret, "failed to write, error %u\n", GetLastError()); + ok(size == 4, "got size %u\n", size); + + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 6, "got size %I64d\n", file_size.QuadPart); + + SetFilePointer(file, 0, NULL, SEEK_SET); + ret = ReadFile(file, buffer, sizeof(buffer), &size, NULL); + ok(ret, "failed to read, error %u\n", GetLastError()); + ok(size == 6, "got size %u\n", size); + ok(!memcmp(buffer, "\0\0data", 6), "wrong data\n"); + + for (i = 0; i < ARRAY_SIZE(map_tests); ++i) + { + mapping = CreateFileMappingA(file, NULL, map_tests[i].protection, 0, 4, NULL); + ok(!!mapping, "failed to create mapping, error %u\n", GetLastError()); + + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 6, "got size %I64d\n", file_size.QuadPart); + + SetFilePointer(file, 6, NULL, SEEK_SET); + ret = SetEndOfFile(file); + ok(ret, "failed to set EOF, error %u\n", GetLastError()); + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 6, "got size %I64d\n", file_size.QuadPart); + + SetFilePointer(file, 8, NULL, SEEK_SET); + ret = SetEndOfFile(file); + ok(ret, "failed to set EOF, error %u\n", GetLastError()); + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 8, "got size %I64d\n", file_size.QuadPart); + + SetLastError(0xdeadbeef); + SetFilePointer(file, 6, NULL, SEEK_SET); + ret = SetEndOfFile(file); + todo_wine ok(!ret, "expected failure\n"); + todo_wine ok(GetLastError() == ERROR_USER_MAPPED_FILE, "got error %u\n", GetLastError()); + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + todo_wine ok(file_size.QuadPart == 8, "got size %I64d\n", file_size.QuadPart); + + SetFilePointer(file, 8192, NULL, SEEK_SET); + ret = SetEndOfFile(file); + ok(ret, "failed to set EOF, error %u\n", GetLastError()); + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 8192, "got size %I64d\n", file_size.QuadPart); + + SetFilePointer(file, 8191, NULL, SEEK_SET); + ret = SetEndOfFile(file); + todo_wine ok(!ret, "expected failure\n"); + todo_wine ok(GetLastError() == ERROR_USER_MAPPED_FILE, "got error %u\n", GetLastError()); + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + todo_wine ok(file_size.QuadPart == 8192, "got size %I64d\n", file_size.QuadPart); + + view = MapViewOfFile(mapping, map_tests[i].view_access, 0, 0, 4); + ok(!!view, "failed to map view, error %u\n", GetLastError()); + + CloseHandle(mapping); + + SetFilePointer(file, 16384, NULL, SEEK_SET); + ret = SetEndOfFile(file); + ok(ret, "failed to set EOF, error %u\n", GetLastError()); + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 16384, "got size %I64d\n", file_size.QuadPart); + + SetFilePointer(file, 16383, NULL, SEEK_SET); + ret = SetEndOfFile(file); + todo_wine ok(!ret, "expected failure\n"); + todo_wine ok(GetLastError() == ERROR_USER_MAPPED_FILE, "got error %u\n", GetLastError()); + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + todo_wine ok(file_size.QuadPart == 16384, "got size %I64d\n", file_size.QuadPart); + + ret = UnmapViewOfFile(view); + ok(ret, "failed to unmap view, error %u\n", GetLastError()); + + SetFilePointer(file, 6, NULL, SEEK_SET); + ret = SetEndOfFile(file); + ok(ret, "failed to set EOF, error %u\n", GetLastError()); + ret = GetFileSizeEx(file, &file_size); + ok(ret, "failed to get size, error %u\n", GetLastError()); + ok(file_size.QuadPart == 6, "got size %I64d\n", file_size.QuadPart); + } + + CloseHandle(file); + ret = DeleteFileA(filename); + ok(ret, "failed to delete %s, error %u\n", debugstr_a(filename), GetLastError()); +} + START_TEST(file) { char temp_path[MAX_PATH]; @@ -6001,4 +6186,5 @@ START_TEST(file) test_ReOpenFile(); test_hard_link(); test_move_file(); + test_eof(); }
From: Qian Hong qhong@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/unix/file.c | 23 +++++----------------- server/fd.c | 43 ++++++++++++++++++++++++++++++++++++++++++ server/protocol.def | 7 +++++++ 3 files changed, 55 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 21f5d10f3f8..1a57a112a59 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4360,28 +4360,15 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, case FileEndOfFileInformation: if (len >= sizeof(FILE_END_OF_FILE_INFORMATION)) { - struct stat st; const FILE_END_OF_FILE_INFORMATION *info = ptr;
- if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) - return io->u.Status; - - /* first try normal truncate */ - if (ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) != -1) break; - - /* now check for the need to extend the file */ - if (fstat( fd, &st ) != -1 && (off_t)info->EndOfFile.QuadPart > st.st_size) + SERVER_START_REQ( set_fd_eof_info ) { - static const char zero; - - /* extend the file one byte beyond the requested size and then truncate it */ - /* this should work around ftruncate implementations that can't extend files */ - if (pwrite( fd, &zero, 1, (off_t)info->EndOfFile.QuadPart ) != -1 && - ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) != -1) break; + req->handle = wine_server_obj_handle( handle ); + req->eof = info->EndOfFile.QuadPart; + io->u.Status = wine_server_call( req ); } - io->u.Status = errno_to_status( errno ); - - if (needs_close) close( fd ); + SERVER_END_REQ; } else io->u.Status = STATUS_INVALID_PARAMETER_3; break; diff --git a/server/fd.c b/server/fd.c index e326354d127..fe97ca01c98 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2630,6 +2630,38 @@ failed: free( name ); }
+static void set_fd_eof( struct fd *fd, file_pos_t eof ) +{ + static const char zero; + struct stat st; + + if (!fd->inode) + { + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return; + } + + if (fd->unix_fd == -1) + { + set_error( fd->no_fd_status ); + return; + } + + /* first try normal truncate */ + if (ftruncate( fd->unix_fd, eof ) != -1) return; + + /* now check for the need to extend the file */ + if (fstat( fd->unix_fd, &st ) != -1 && eof > st.st_size) + { + /* extend the file one byte beyond the requested size and then truncate it */ + /* this should work around ftruncate implementations that can't extend files */ + if (pwrite( fd->unix_fd, &zero, 1, eof ) != -1 && + ftruncate( fd->unix_fd, eof) != -1) return; + } + + file_set_error(); +} + struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key ) { *p_key = fd->comp_key; @@ -2922,3 +2954,14 @@ DECL_HANDLER(set_fd_name_info) } if (root_fd) release_object( root_fd ); } + +/* set fd eof information */ +DECL_HANDLER(set_fd_eof_info) +{ + struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 ); + if (fd) + { + set_fd_eof( fd, req->eof ); + release_object( fd ); + } +} diff --git a/server/protocol.def b/server/protocol.def index 6a11dfac77d..6a92a4f8e74 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3534,6 +3534,13 @@ struct handle_info @END
+/* set fd eof information */ +@REQ(set_fd_eof_info) + obj_handle_t handle; /* handle to a file or directory */ + file_pos_t eof; /* offset of eof of file */ +@END + + /* Retrieve layered info for a window */ @REQ(get_window_layered_info) user_handle_t handle; /* handle to the window */
From: Qian Hong qhong@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- This patch had a corresponding entry in the old wine-staging bug tracker (bug 471). I could not find any details relating to the bug, except that it is related to msys2.
dlls/kernel32/tests/file.c | 18 +++++++++--------- server/fd.c | 21 ++++++++++++++++++++- 2 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index c09438e09bd..ea0a32f258d 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -6052,11 +6052,11 @@ static void test_eof(void) SetLastError(0xdeadbeef); SetFilePointer(file, 6, NULL, SEEK_SET); ret = SetEndOfFile(file); - todo_wine ok(!ret, "expected failure\n"); - todo_wine ok(GetLastError() == ERROR_USER_MAPPED_FILE, "got error %u\n", GetLastError()); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_USER_MAPPED_FILE, "got error %u\n", GetLastError()); ret = GetFileSizeEx(file, &file_size); ok(ret, "failed to get size, error %u\n", GetLastError()); - todo_wine ok(file_size.QuadPart == 8, "got size %I64d\n", file_size.QuadPart); + ok(file_size.QuadPart == 8, "got size %I64d\n", file_size.QuadPart);
SetFilePointer(file, 8192, NULL, SEEK_SET); ret = SetEndOfFile(file); @@ -6067,11 +6067,11 @@ static void test_eof(void)
SetFilePointer(file, 8191, NULL, SEEK_SET); ret = SetEndOfFile(file); - todo_wine ok(!ret, "expected failure\n"); - todo_wine ok(GetLastError() == ERROR_USER_MAPPED_FILE, "got error %u\n", GetLastError()); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_USER_MAPPED_FILE, "got error %u\n", GetLastError()); ret = GetFileSizeEx(file, &file_size); ok(ret, "failed to get size, error %u\n", GetLastError()); - todo_wine ok(file_size.QuadPart == 8192, "got size %I64d\n", file_size.QuadPart); + ok(file_size.QuadPart == 8192, "got size %I64d\n", file_size.QuadPart);
view = MapViewOfFile(mapping, map_tests[i].view_access, 0, 0, 4); ok(!!view, "failed to map view, error %u\n", GetLastError()); @@ -6087,11 +6087,11 @@ static void test_eof(void)
SetFilePointer(file, 16383, NULL, SEEK_SET); ret = SetEndOfFile(file); - todo_wine ok(!ret, "expected failure\n"); - todo_wine ok(GetLastError() == ERROR_USER_MAPPED_FILE, "got error %u\n", GetLastError()); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_USER_MAPPED_FILE, "got error %u\n", GetLastError()); ret = GetFileSizeEx(file, &file_size); ok(ret, "failed to get size, error %u\n", GetLastError()); - todo_wine ok(file_size.QuadPart == 16384, "got size %I64d\n", file_size.QuadPart); + ok(file_size.QuadPart == 16384, "got size %I64d\n", file_size.QuadPart);
ret = UnmapViewOfFile(view); ok(ret, "failed to unmap view, error %u\n", GetLastError()); diff --git a/server/fd.c b/server/fd.c index fe97ca01c98..99fe103c87c 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2647,11 +2647,30 @@ static void set_fd_eof( struct fd *fd, file_pos_t eof ) return; }
+ if (fstat( fd->unix_fd, &st) == -1) + { + file_set_error(); + return; + } + + if (eof < st.st_size) + { + struct fd *fd_ptr; + LIST_FOR_EACH_ENTRY( fd_ptr, &fd->inode->open, struct fd, inode_entry ) + { + if (fd_ptr->access & FILE_MAPPING_ACCESS) + { + set_error( STATUS_USER_MAPPED_FILE ); + return; + } + } + } + /* first try normal truncate */ if (ftruncate( fd->unix_fd, eof ) != -1) return;
/* now check for the need to extend the file */ - if (fstat( fd->unix_fd, &st ) != -1 && eof > st.st_size) + if (eof > st.st_size) { /* extend the file one byte beyond the requested size and then truncate it */ /* this should work around ftruncate implementations that can't extend files */