Skip to content

Commit

Permalink
td.windows: use atomic rename, if possible
Browse files Browse the repository at this point in the history
Mitigates ziglang#14978.
  • Loading branch information
matu3ba committed May 19, 2023
1 parent b61d0de commit 4b4c53e
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 19 deletions.
49 changes: 36 additions & 13 deletions lib/std/os.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2679,23 +2679,46 @@ pub fn renameatW(

const rename_info = @ptrCast(*windows.FILE_RENAME_INFORMATION, &rename_info_buf);

rename_info.* = .{
.ReplaceIfExists = ReplaceIfExists,
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(new_path_w)) null else new_dir_fd,
.FileNameLength = @intCast(u32, new_path_w.len * 2), // already checked error.NameTooLong
.FileName = undefined,
};
if (builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) {
var flags: windows.ULONG = windows.FILE_RENAME_POSIX_SEMANTICS | windows.FILE_RENAME_IGNORE_READONLY_ATTRIBUTE;
if (ReplaceIfExists) flags |= windows.FILE_RENAME_REPLACE_IF_EXISTS;
rename_info.* = .{
.anon1 = .{
.Flags = flags,
},
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(new_path_w)) null else new_dir_fd,
.FileNameLength = @intCast(u32, new_path_w.len * 2), // already checked error.NameTooLong
.FileName = undefined,
};
} else {
rename_info.* = .{
.ReplaceIfExists = ReplaceIfExists,
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(new_path_w)) null else new_dir_fd,
.FileNameLength = @intCast(u32, new_path_w.len * 2), // already checked error.NameTooLong
.FileName = undefined,
};
}
@memcpy(@as([*]u16, &rename_info.FileName)[0..new_path_w.len], new_path_w);

var io_status_block: windows.IO_STATUS_BLOCK = undefined;

const rc = windows.ntdll.NtSetInformationFile(
src_fd,
&io_status_block,
rename_info,
@intCast(u32, struct_len), // already checked for error.NameTooLong
.FileRenameInformation,
);
const rc = if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) {
windows.ntdll.NtSetInformationFile(
src_fd,
&io_status_block,
rename_info,
@intCast(u32, struct_len), // already checked for error.NameTooLong
.FileRenameInformation,
);
} else {
windows.ntdll.NtSetInformationFile(
src_fd,
&io_status_block,
rename_info,
@intCast(u32, struct_len), // already checked for error.NameTooLong
.FileRenameInformation,
);
};

switch (rc) {
.SUCCESS => return,
Expand Down
36 changes: 30 additions & 6 deletions lib/std/os/windows.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2397,12 +2397,36 @@ pub const FILE_NAME_INFORMATION = extern struct {
FileName: [1]WCHAR,
};

pub const FILE_RENAME_INFORMATION = extern struct {
ReplaceIfExists: BOOLEAN,
RootDirectory: ?HANDLE,
FileNameLength: ULONG,
FileName: [1]WCHAR,
};
// FILE_RENAME_INFORMATION.anon1.Flags
pub const FILE_RENAME_REPLACE_IF_EXISTS = 0x00000001;
pub const FILE_RENAME_POSIX_SEMANTICS = 0x00000002;
pub const FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE = 0x00000004;
pub const FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE = 0x00000008;
pub const FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE = 0x00000010;
pub const FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE = 0x00000020;
pub const FILE_RENAME_PRESERVE_AVAILABLE_SPACE = 0x00000030;
pub const FILE_RENAME_IGNORE_READONLY_ATTRIBUTE = 0x00000040;
pub const FILE_RENAME_FORCE_RESIZE_TARGET_SR = 0x00000080;
pub const FILE_RENAME_FORCE_RESIZE_SOURCE_SR = 0x00000100;
pub const FILE_RENAME_FORCE_RESIZE_SR = 0x00000180;

pub const FILE_RENAME_INFORMATION = if (builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1))
extern struct {
anon1: union {
ReplaceIfExists: BOOLEAN,
Flags: ULONG,
},
RootDirectory: ?HANDLE,
FileNameLength: ULONG,
FileName: [1]WCHAR,
}
else
extern struct {
ReplaceIfExists: BOOLEAN,
RootDirectory: ?HANDLE,
FileNameLength: ULONG,
FileName: [1]WCHAR,
};

pub const IO_STATUS_BLOCK = extern struct {
// "DUMMYUNIONNAME" expands to "u"
Expand Down

0 comments on commit 4b4c53e

Please sign in to comment.