[PATCH v4 0/2] 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. -- v4: Used posix_fallocate in place of ftruncate + added related test Merge remote-tracking branch 'main/master' into 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
@hans I pushed posix_fallocate version + tests, using other parts of the code as a template. For unknown reason, the CI still complains about identity with my MRs (I double checked that all my commits where done with user.name / user.email set). If you can/want to use this code, improve it with your better understanding of wine / multi-threading potential issues, please do. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7115#note_93767
You need to get rid of the merge commits with git-rebase. And posix_fallocate() has the same problem as ftruncate() with respect to increasing the size of the file. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7115#note_93778
There's fallocate(FALLOC_FL_KEEP_SIZE) which doesn't increase file size but it's Linux-specific. I guess that's acceptable. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7115#note_93838
@julliard I still don't get the reason of your concern about the file size increase. That's what the function is aimed to do, as far as I understand it. What is your interpretation of it, if not the same? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7115#note_93859
It allocates space but it doesn't increase the file size. If you run your test on Windows you'll see a failure, because the file size doesn't change. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7115#note_93866
@julliard Ok, got you. Thanks. Shall I use fallocate with the KEEP_SIZE flag as suggested by Hans, then? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7115#note_93889
Yes, something like that. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7115#note_93891
participants (4)
-
Alexandre Julliard (@julliard) -
Hans Leidekker (@hans) -
Stephane Bacri -
Stéphane Bacri