[PATCH v7 0/4] MR7115: Added support of case FileAllocationInformation in SetFileInformationByHandle
This MR intends to add support for the case FileAllocationInformation in function SetFileInformationByHandle of library kernelbase.dll. The code is based on my understanding of [MS documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntif...) No test was added, because other cases that could have helped doing so (FileEndOfFileInformation) do not have neither. -- v7: removed probably useless FALLOC_FL_ZERO_RANGE flag Switched back to fallocate, with FALLOC_FL_KEEP_SIZE Used posix_fallocate in place of ftruncate + added related test Added support of sub function FileAllocationInformation in SetFileInformationByHandle https://gitlab.winehq.org/wine/wine/-/merge_requests/7115
From: Stephane Bacri <frisou76(a)yahoo.fr> --- dlls/kernelbase/file.c | 5 ++++- dlls/ntdll/unix/file.c | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index f0dedfe3b14..416892ef14c 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -3678,7 +3678,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetFileInformationByHandle( HANDLE file, FILE_INFO switch (class) { case FileNameInfo: - case FileAllocationInfo: case FileStreamInfo: case FileIdBothDirectoryInfo: case FileIdBothDirectoryRestartInfo: @@ -3693,6 +3692,10 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetFileInformationByHandle( HANDLE file, FILE_INFO SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); return FALSE; + case FileAllocationInfo: + status = NtSetInformationFile( file, &io, info, size, FileAllocationInformation ); + break; + case FileEndOfFileInfo: status = NtSetInformationFile( file, &io, info, size, FileEndOfFileInformation ); break; diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 8bc69557057..af3052b92e3 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4668,6 +4668,22 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, else status = STATUS_INVALID_PARAMETER_3; break; + case FileAllocationInformation: + if (len >= sizeof(FILE_ALLOCATION_INFORMATION)) + { + const FILE_ALLOCATION_INFORMATION *info = ptr; + + if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + return io->Status = status; + + if (ftruncate(fd, (off_t)info->AllocationSize.QuadPart) == -1) + status = errno_to_status( errno ); + + if (needs_close) close( fd ); + } + else status = STATUS_INVALID_PARAMETER_3; + break; + case FilePositionInformation: if (len >= sizeof(FILE_POSITION_INFORMATION)) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7115
From: Stéphane Bacri <frisou76(a)yahoo.fr> --- dlls/ntdll/tests/file.c | 25 +++++++++++++++++++++++++ dlls/ntdll/unix/file.c | 12 ++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 8465ad4543a..553fc1eb160 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -1334,6 +1334,30 @@ static void test_file_io_completion(void) pNtClose( h ); } +static void test_file_setFileAllocationInformation(void) { + FILE_ALLOCATION_INFORMATION fas; + BY_HANDLE_FILE_INFORMATION info; + IO_STATUS_BLOCK io; + HANDLE handle; + int res; + + if( !(handle = create_temp_file(0)) ) return; + + memset( &fas, 0, sizeof(fas) ); + fas.AllocationSize.QuadPart = 1024 * 1024; + res = pNtSetInformationFile( handle, &io, &fas, sizeof fas, FileAllocationInformation ); + + ok ( res == STATUS_SUCCESS, "file allocation failed, NtSetInformationFile returned %x\n", res ); + ok ( io.Status == STATUS_SUCCESS, "file allocation failed, io.Status is %lx\n", io.Status ); + + memset( &info, 0x22, sizeof(info) ); + res = GetFileInformationByHandle( handle, &info ); + ok( res, "GetFileInformationByHandle failed\n" ); + ok( info.nFileSizeLow == fas.AllocationSize.QuadPart, "incorrect file size after allocation\n" ); + + CloseHandle( handle ); +} + static void test_file_full_size_information(void) { IO_STATUS_BLOCK io; @@ -6114,6 +6138,7 @@ START_TEST(file) test_file_access_information(); test_file_attribute_tag_information(); test_file_stat_information(); + test_file_setFileAllocationInformation(); test_dotfile_file_attributes(); test_file_mode(); test_file_readonly_access(); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index af3052b92e3..177e343a311 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4672,12 +4672,20 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, if (len >= sizeof(FILE_ALLOCATION_INFORMATION)) { const FILE_ALLOCATION_INFORMATION *info = ptr; + int err; if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) return io->Status = status; - if (ftruncate(fd, (off_t)info->AllocationSize.QuadPart) == -1) - status = errno_to_status( errno ); +#ifdef HAVE_POSIX_FALLOCATE + if ((err = posix_fallocate( fd, 0, (off_t)info->AllocationSize.QuadPart )) != 0) + { + if (err == EOPNOTSUPP) WARN( "posix_fallocate not supported on this filesystem\n" ); + else status = errno_to_status( err ); + } +#else + WARN( "setting file allocation information not supported\n" ); +#endif if (needs_close) close( fd ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7115
From: Stéphane Bacri <frisou76(a)yahoo.fr> --- dlls/ntdll/tests/file.c | 25 ++++++++++++++++++++++--- dlls/ntdll/unix/file.c | 12 ++---------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 553fc1eb160..56f572cb418 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -1340,11 +1340,16 @@ static void test_file_setFileAllocationInformation(void) { IO_STATUS_BLOCK io; HANDLE handle; int res; + char* buffer; + DWORD bytesWritten, bytesRead; + DWORD length = 64*1024; + LARGE_INTEGER distanceToMove; + distanceToMove.QuadPart = 0; if( !(handle = create_temp_file(0)) ) return; memset( &fas, 0, sizeof(fas) ); - fas.AllocationSize.QuadPart = 1024 * 1024; + fas.AllocationSize.QuadPart = length; res = pNtSetInformationFile( handle, &io, &fas, sizeof fas, FileAllocationInformation ); ok ( res == STATUS_SUCCESS, "file allocation failed, NtSetInformationFile returned %x\n", res ); @@ -1353,8 +1358,22 @@ static void test_file_setFileAllocationInformation(void) { memset( &info, 0x22, sizeof(info) ); res = GetFileInformationByHandle( handle, &info ); ok( res, "GetFileInformationByHandle failed\n" ); - ok( info.nFileSizeLow == fas.AllocationSize.QuadPart, "incorrect file size after allocation\n" ); - + ok( info.nFileSizeLow == 0, "incorrect file size after allocation: should be 0, got %lx\n", info.nFileSizeLow ); + + buffer = malloc(length); + memset( buffer, 0xa5, length ); + res = WriteFile( handle, buffer, length, &bytesWritten, NULL ); + ok ( res != 0 , "couldn't write to file after allocation\n"); + ok ( bytesWritten == length, "couldn't write to whole or part of file after allocation: allocated %lx, written %lx\n", length, bytesWritten ); + + memset( buffer, 0, length ); + SetFilePointerEx( handle, distanceToMove, NULL, FILE_BEGIN ); + res = ReadFile( handle, buffer, length, &bytesRead, NULL ); + ok ( res != 0 , "couldn't read file after allocation\n" ); + ok ( bytesRead == length, "couldn't read whole or part of file after allocation: allocated %lx, read %lx\n", length, bytesRead ); + ok ( *buffer == (char)0xa5, "data read from allocated file doesn't match written pattern: wrote 0xa5, got 0x%x\n", *buffer & 0xff ); + + free(buffer); CloseHandle( handle ); } diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 177e343a311..ddbe927a6be 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4672,20 +4672,12 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, if (len >= sizeof(FILE_ALLOCATION_INFORMATION)) { const FILE_ALLOCATION_INFORMATION *info = ptr; - int err; if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) return io->Status = status; -#ifdef HAVE_POSIX_FALLOCATE - if ((err = posix_fallocate( fd, 0, (off_t)info->AllocationSize.QuadPart )) != 0) - { - if (err == EOPNOTSUPP) WARN( "posix_fallocate not supported on this filesystem\n" ); - else status = errno_to_status( err ); - } -#else - WARN( "setting file allocation information not supported\n" ); -#endif + if (fallocate( fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_ZERO_RANGE, 0, (off_t)info->AllocationSize.QuadPart ) == -1) + status = errno_to_status( errno ); if (needs_close) close( fd ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7115
From: Stéphane Bacri <frisou76(a)yahoo.fr> --- dlls/ntdll/unix/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index ddbe927a6be..e889fc87fcd 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4676,7 +4676,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) return io->Status = status; - if (fallocate( fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_ZERO_RANGE, 0, (off_t)info->AllocationSize.QuadPart ) == -1) + if (fallocate( fd, FALLOC_FL_KEEP_SIZE, 0, (off_t)info->AllocationSize.QuadPart ) == -1) status = errno_to_status( errno ); if (needs_close) close( fd ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7115
@hans @julliard Couldn't manage that earlier, sorry about that. As discussed, I used the fallocate with FALLOC_FL_KEEP_SIZE. After few merge / rebase trials that may have blurred the history a bit, it looks like the CI eventually ended building. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7115#note_95646
Please put the tests in a separate commit and squash the implementation commits. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7115#note_95649
participants (3)
-
Hans Leidekker (@hans) -
Stephane Bacri -
Stéphane Bacri