about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-12-24 22:00:05 +0000
committerbors <bors@rust-lang.org>2024-12-24 22:00:05 +0000
commita92c3cf04d945aa2071067ef299bfacec7bfebe4 (patch)
tree6a1522c8cd2c83cbb57e810b79c5e6968fa7606d
parent409998c4e8cae45344fd434b358b697cc93870d0 (diff)
parentca56dc853714cc6f939a4c735bfc119842896d83 (diff)
downloadrust-a92c3cf04d945aa2071067ef299bfacec7bfebe4.tar.gz
rust-a92c3cf04d945aa2071067ef299bfacec7bfebe4.zip
Auto merge of #134722 - ChrisDenton:trunc, r=Amanieu
Windows: Use FILE_ALLOCATION_INFO for truncation

We use `FILE_END_OF_FILE_INFO` here only because WINE does not support `FILE_ALLOCATION_INFO`. Instead of going with the one with broadest support, let's just use that as fallback only.
-rw-r--r--library/std/src/sys/pal/windows/fs.rs28
1 files changed, 20 insertions, 8 deletions
diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs
index 642be872dce..dda4259919b 100644
--- a/library/std/src/sys/pal/windows/fs.rs
+++ b/library/std/src/sys/pal/windows/fs.rs
@@ -316,19 +316,31 @@ impl File {
                 && api::get_last_error() == WinError::ALREADY_EXISTS
             {
                 unsafe {
-                    // This originally used `FileAllocationInfo` instead of
-                    // `FileEndOfFileInfo` but that wasn't supported by WINE.
-                    // It's arguable which fits the semantics of `OpenOptions`
-                    // better so let's just use the more widely supported method.
-                    let eof = c::FILE_END_OF_FILE_INFO { EndOfFile: 0 };
+                    // This first tries `FileAllocationInfo` but falls back to
+                    // `FileEndOfFileInfo` in order to support WINE.
+                    // If WINE gains support for FileAllocationInfo, we should
+                    // remove the fallback.
+                    let alloc = c::FILE_ALLOCATION_INFO { AllocationSize: 0 };
                     let result = c::SetFileInformationByHandle(
                         handle.as_raw_handle(),
                         c::FileEndOfFileInfo,
-                        (&raw const eof).cast::<c_void>(),
-                        mem::size_of::<c::FILE_END_OF_FILE_INFO>() as u32,
+                        (&raw const alloc).cast::<c_void>(),
+                        mem::size_of::<c::FILE_ALLOCATION_INFO>() as u32,
                     );
                     if result == 0 {
-                        return Err(io::Error::last_os_error());
+                        if api::get_last_error().code != 0 {
+                            panic!("FILE_ALLOCATION_INFO failed!!!");
+                        }
+                        let eof = c::FILE_END_OF_FILE_INFO { EndOfFile: 0 };
+                        let result = c::SetFileInformationByHandle(
+                            handle.as_raw_handle(),
+                            c::FileEndOfFileInfo,
+                            (&raw const eof).cast::<c_void>(),
+                            mem::size_of::<c::FILE_END_OF_FILE_INFO>() as u32,
+                        );
+                        if result == 0 {
+                            return Err(io::Error::last_os_error());
+                        }
                     }
                 }
             }