-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path221983.mypatch
119 lines (111 loc) · 4.65 KB
/
221983.mypatch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
From: Patrick Hibbs <[email protected]>
Subject: [PATCH 1/2] ntdll: Implement alloc_size support in NtCreateFile.
Message-Id: <[email protected]>
Date: Fri, 10 Dec 2021 21:08:30 -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 <[email protected]>
---
dlls/ntdll/unix/file.c | 73 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 70 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 51c92df57e3..07204a8553d 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -3743,6 +3743,10 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
char *unix_name;
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)
{
@@ -4052,6 +4052,71 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
status = STATUS_SUCCESS;
}
+#ifdef HAVE_POSIX_FALLOCATE
+ /* Windows doesn't care about the requested access permissions
+ * when performing space reservation. (Windows will trim / grow
+ * the reserved space even if a caller requests read-only
+ * access.)
+ *
+ * Windows *does* care about the disposition given and whether
+ * or not an overwrite will actually occur. (Windows will return
+ * STATUS_OBJECT_NAME_NOT_FOUND if disposition is FILE_OVERWRITE
+ * and the file doesn't exist.)
+ *
+ * POSIX cares about the requested permissions all of the time.
+ * We need to make sure that we ask for enough permissions to
+ * perform the disk space reservation. Afterwards reopen the file
+ * with the desired permissions. As this temporary fd isn't going
+ * to be kept anyway, avoid the round trips to the server by doing
+ * the work here. */
+ 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( handle, unix_name, options, &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)
{
WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), io->u.Status );
@@ -4059,7 +4124,7 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
}
status = open_unix_file( handle, unix_name, access, &new_attr, attributes,
- sharing, disposition, options, ea_buffer, ea_length );
+ sharing, new_disposition, options, ea_buffer, ea_length );
if (status == STATUS_SUCCESS)
{