diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2023-11-27 22:48:50 +0100 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2023-11-28 10:55:38 +0100 |
commit | f64f3eced8e0f51753bc199f3ba96fab06a54848 (patch) | |
tree | 49469f3ec06191c031172782e3ec191a484b67c4 /winsup | |
parent | 114f89caff7b9b62b0b12bc2c6d143daf47b8042 (diff) | |
download | newlib-f64f3eced8e0f51753bc199f3ba96fab06a54848.zip newlib-f64f3eced8e0f51753bc199f3ba96fab06a54848.tar.gz newlib-f64f3eced8e0f51753bc199f3ba96fab06a54848.tar.bz2 |
Cygwin: pwrite(2): sparsify file
write(2) sparsifies a file after an lseek far enough beyond EOF.
Let pwrite(2) sparsify as well if offset is far enough beyond EOF.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/fhandler/disk_file.cc | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/winsup/cygwin/fhandler/disk_file.cc b/winsup/cygwin/fhandler/disk_file.cc index b49b25c..c70afed 100644 --- a/winsup/cygwin/fhandler/disk_file.cc +++ b/winsup/cygwin/fhandler/disk_file.cc @@ -1724,6 +1724,7 @@ fhandler_disk_file::pwrite (void *buf, size_t count, off_t offset, void *aio) { NTSTATUS status; IO_STATUS_BLOCK io; + FILE_STANDARD_INFORMATION fsi; LARGE_INTEGER off = { QuadPart:offset }; HANDLE evt = aio ? (HANDLE) aiocb->aio_wincb.event : NULL; PIO_STATUS_BLOCK pio = aio ? (PIO_STATUS_BLOCK) &aiocb->aio_wincb : &io; @@ -1732,6 +1733,25 @@ fhandler_disk_file::pwrite (void *buf, size_t count, off_t offset, void *aio) if (prw_handle && (prw_handle_isasync != !!aio)) NtClose (prw_handle), prw_handle = NULL; + /* If the file system supports sparse files and the application is + writing beyond EOF spanning more than one sparsifiable chunk, + convert the file to a sparse file. */ + if (pc.support_sparse () + && !has_attribute (FILE_ATTRIBUTE_SPARSE_FILE) + && NT_SUCCESS (NtQueryInformationFile (get_handle (), + &io, &fsi, sizeof fsi, + FileStandardInformation)) + && offset >= fsi.EndOfFile.QuadPart + (128 * 1024)) + { + NTSTATUS status; + status = NtFsControlFile (get_handle (), NULL, NULL, NULL, + &io, FSCTL_SET_SPARSE, NULL, 0, NULL, 0); + if (NT_SUCCESS (status)) + pc.file_attributes (pc.file_attributes () + | FILE_ATTRIBUTE_SPARSE_FILE); + debug_printf ("%y = NtFsControlFile(%S, FSCTL_SET_SPARSE)", + status, pc.get_nt_native_path ()); + } if (!prw_handle && prw_open (true, aio)) goto non_atomic; status = NtWriteFile (prw_handle, evt, NULL, NULL, pio, buf, count, |