From: Patrick Hibbs Subject: [PATCH v2 1/2] ntdll: Implement alloc_size support in NtCreateFile. Message-Id: <20220126134903.397709-1-hibbsncc1701@gmail.com> Date: Wed, 26 Jan 2022 08:49:02 -0500 Use posix_fallocate to reserve space for files. Function will print a warning at runtime if posix_fallocate isn't supported. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52171 Signed-off-by: Patrick Hibbs --- v2: - Rebase to current master after codefreeze. - Remove unneeded comment block. - Fix memory leak pointed out by Alex Henrie. --- dlls/ntdll/unix/file.c | 61 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index a29b5cbb980..259c4c3b795 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -3740,9 +3740,13 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU { OBJECT_ATTRIBUTES new_attr; UNICODE_STRING nt_name; - char *unix_name; + char *unix_name = NULL; BOOL created = FALSE; NTSTATUS status; + ULONG new_attributes, new_disposition; + struct stat st; + LARGE_INTEGER remaining_bytes; + int perr, unix_handle; TRACE( "handle=%p access=%08x name=%s objattr=%08x root=%p sec=%p io=%p alloc_size=%p " "attr=%08x sharing=%08x disp=%d options=%08x ea=%p.0x%08x\n", @@ -3753,8 +3757,6 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU *handle = 0; if (!attr || !attr->ObjectName) return STATUS_INVALID_PARAMETER; - if (alloc_size) FIXME( "alloc_size not supported\n" ); - new_attr = *attr; if (options & FILE_OPEN_BY_FILE_ID) { @@ -3781,11 +3783,59 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU status = STATUS_SUCCESS; } +#ifdef HAVE_POSIX_FALLOCATE + if (alloc_size && alloc_size->QuadPart > 0 && + disposition != FILE_OPEN && + (created || (disposition != FILE_OVERWRITE || + status != STATUS_OBJECT_NAME_NOT_FOUND))) + { + remaining_bytes.QuadPart = 0; + new_disposition = FILE_OPEN; + + if (created) + remaining_bytes.QuadPart = alloc_size->QuadPart; + else + { + if (get_file_info( unix_name, &st, &new_attributes ) == -1) + status = errno_to_status( errno ); + else + { + if ((S_ISREG(st.st_mode)) && ((st.st_blocks * 512) < alloc_size->QuadPart)) + remaining_bytes.QuadPart = (alloc_size->QuadPart - (st.st_blocks * 512)); + } + } + + if (remaining_bytes.QuadPart > 0) + { + if (created || disposition == FILE_SUPERSEDE || disposition == FILE_OVERWRITE) + unix_handle = open( unix_name, O_RDWR | O_CREAT | O_TRUNC | O_DIRECT | O_SYNC, S_IRWXU ); + else + unix_handle = open( unix_name, O_RDWR | O_DIRECT | O_SYNC, S_IRWXU ); + + if (unix_handle == -1) + status = errno_to_status( errno ); + else + { + perr = posix_fallocate( unix_handle, 0, remaining_bytes.QuadPart ); + if (perr) + status = errno_to_status( perr ); + + close( unix_handle ); + } + } + } + else + { + new_disposition = disposition; + } +#else + WARN_ONCE("Preallocating files is not supported!\n"); +#endif + if (status == STATUS_SUCCESS) { status = open_unix_file( handle, unix_name, access, &new_attr, attributes, - sharing, disposition, options, ea_buffer, ea_length ); - free( unix_name ); + sharing, new_disposition, options, ea_buffer, ea_length ); } else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status ); @@ -3816,6 +3866,7 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU if (!once++) ERR_(winediag)( "Too many open files, ulimit -n probably needs to be increased\n" ); } + if (unix_name) free( unix_name ); free( nt_name.Buffer ); return io->u.Status = status; } -- 2.30.2