@@ -2629,14 +2629,16 @@ pub fn renameatW(
2629
2629
};
2630
2630
defer windows .CloseHandle (src_fd );
2631
2631
2632
- const struct_buf_len = @sizeOf (windows .FILE_RENAME_INFORMATION ) + (MAX_PATH_BYTES - 1 );
2633
- var rename_info_buf : [struct_buf_len ]u8 align (@alignOf (windows .FILE_RENAME_INFORMATION )) = undefined ;
2634
- const struct_len = @sizeOf (windows .FILE_RENAME_INFORMATION ) - 1 + new_path_w .len * 2 ;
2635
- if (struct_len > struct_buf_len ) return error .NameTooLong ;
2636
-
2637
- const rename_info = @as (* windows .FILE_RENAME_INFORMATION , @ptrCast (& rename_info_buf ));
2632
+ var need_fallback = true ;
2633
+ if (comptime builtin .target .os .version_range .windows .min .isAtLeast (.win10_rs1 )) {
2634
+ const struct_buf_len = @sizeOf (windows .FILE_RENAME_INFORMATION_EX ) + (MAX_PATH_BYTES - 1 );
2635
+ var rename_info_buf : [struct_buf_len ]u8 align (@alignOf (windows .FILE_RENAME_INFORMATION_EX )) = undefined ;
2636
+ const struct_len = @sizeOf (windows .FILE_RENAME_INFORMATION_EX ) - 1 + new_path_w .len * 2 ;
2637
+ if (struct_len > struct_buf_len ) return error .NameTooLong ;
2638
+
2639
+ const rename_info = @as (* windows .FILE_RENAME_INFORMATION_EX , @ptrCast (& rename_info_buf ));
2640
+ var io_status_block : windows.IO_STATUS_BLOCK = undefined ;
2638
2641
2639
- if (builtin .target .os .version_range .windows .min .isAtLeast (.win10_rs1 )) {
2640
2642
var flags : windows.ULONG = windows .FILE_RENAME_POSIX_SEMANTICS | windows .FILE_RENAME_IGNORE_READONLY_ATTRIBUTE ;
2641
2643
if (ReplaceIfExists == windows .TRUE ) flags |= windows .FILE_RENAME_REPLACE_IF_EXISTS ;
2642
2644
rename_info .* = .{
@@ -2645,47 +2647,61 @@ pub fn renameatW(
2645
2647
.FileNameLength = @intCast (new_path_w .len * 2 ), // already checked error.NameTooLong
2646
2648
.FileName = undefined ,
2647
2649
};
2648
- } else {
2650
+ @memcpy (@as ([* ]u16 , & rename_info .FileName )[0.. new_path_w .len ], new_path_w );
2651
+ const rc = windows .ntdll .NtSetInformationFile (
2652
+ src_fd ,
2653
+ & io_status_block ,
2654
+ rename_info ,
2655
+ @intCast (struct_len ), // already checked for error.NameTooLong
2656
+ .FileRenameInformationEx ,
2657
+ );
2658
+ switch (rc ) {
2659
+ .SUCCESS = > return ,
2660
+ // INVALID_PARAMETER here means that the filesystem does not support FileRenameInformationEx
2661
+ .INVALID_PARAMETER = > {},
2662
+ // For all other statuses, fall down to the switch below to handle them.
2663
+ else = > need_fallback = false ,
2664
+ }
2665
+ }
2666
+
2667
+ if (need_fallback ) {
2668
+ const struct_buf_len = @sizeOf (windows .FILE_RENAME_INFORMATION ) + (MAX_PATH_BYTES - 1 );
2669
+ var rename_info_buf : [struct_buf_len ]u8 align (@alignOf (windows .FILE_RENAME_INFORMATION )) = undefined ;
2670
+ const struct_len = @sizeOf (windows .FILE_RENAME_INFORMATION ) - 1 + new_path_w .len * 2 ;
2671
+ if (struct_len > struct_buf_len ) return error .NameTooLong ;
2672
+
2673
+ const rename_info = @as (* windows .FILE_RENAME_INFORMATION , @ptrCast (& rename_info_buf ));
2674
+ var io_status_block : windows.IO_STATUS_BLOCK = undefined ;
2675
+
2649
2676
rename_info .* = .{
2650
2677
.Flags = ReplaceIfExists ,
2651
2678
.RootDirectory = if (std .fs .path .isAbsoluteWindowsWTF16 (new_path_w )) null else new_dir_fd ,
2652
2679
.FileNameLength = @intCast (new_path_w .len * 2 ), // already checked error.NameTooLong
2653
2680
.FileName = undefined ,
2654
2681
};
2655
- }
2656
- @memcpy (@as ([* ]u16 , & rename_info .FileName )[0.. new_path_w .len ], new_path_w );
2657
-
2658
- var io_status_block : windows.IO_STATUS_BLOCK = undefined ;
2682
+ @memcpy (@as ([* ]u16 , & rename_info .FileName )[0.. new_path_w .len ], new_path_w );
2659
2683
2660
- const rc = if (comptime builtin .target .os .version_range .windows .min .isAtLeast (.win10_rs1 )) {
2661
- windows .ntdll .NtSetInformationFile (
2662
- src_fd ,
2663
- & io_status_block ,
2664
- rename_info ,
2665
- @intCast (struct_len ), // already checked for error.NameTooLong
2666
- .FileRenameInformationEx ,
2667
- );
2668
- } else {
2669
- windows .ntdll .NtSetInformationFile (
2684
+ const rc =
2685
+ windows .ntdll .NtSetInformationFile (
2670
2686
src_fd ,
2671
2687
& io_status_block ,
2672
2688
rename_info ,
2673
2689
@intCast (struct_len ), // already checked for error.NameTooLong
2674
2690
.FileRenameInformation ,
2675
2691
);
2676
- };
2677
2692
2678
- switch (rc ) {
2679
- .SUCCESS = > return ,
2680
- .INVALID_HANDLE = > unreachable ,
2681
- .INVALID_PARAMETER = > unreachable ,
2682
- .OBJECT_PATH_SYNTAX_BAD = > unreachable ,
2683
- .ACCESS_DENIED = > return error .AccessDenied ,
2684
- .OBJECT_NAME_NOT_FOUND = > return error .FileNotFound ,
2685
- .OBJECT_PATH_NOT_FOUND = > return error .FileNotFound ,
2686
- .NOT_SAME_DEVICE = > return error .RenameAcrossMountPoints ,
2687
- .OBJECT_NAME_COLLISION = > return error .PathAlreadyExists ,
2688
- else = > return windows .unexpectedStatus (rc ),
2693
+ switch (rc ) {
2694
+ .SUCCESS = > {},
2695
+ .INVALID_HANDLE = > unreachable ,
2696
+ .INVALID_PARAMETER = > unreachable ,
2697
+ .OBJECT_PATH_SYNTAX_BAD = > unreachable ,
2698
+ .ACCESS_DENIED = > return error .AccessDenied ,
2699
+ .OBJECT_NAME_NOT_FOUND = > return error .FileNotFound ,
2700
+ .OBJECT_PATH_NOT_FOUND = > return error .FileNotFound ,
2701
+ .NOT_SAME_DEVICE = > return error .RenameAcrossMountPoints ,
2702
+ .OBJECT_NAME_COLLISION = > return error .PathAlreadyExists ,
2703
+ else = > return windows .unexpectedStatus (rc ),
2704
+ }
2689
2705
}
2690
2706
}
2691
2707
0 commit comments