Skip to content

Commit 1a58e0c

Browse files
committed
change rename implementation
1 parent f261cce commit 1a58e0c

File tree

3 files changed

+55
-17
lines changed

3 files changed

+55
-17
lines changed

library/std/src/sys/fs/windows.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ impl Dir {
10291029
to_dir: &Self,
10301030
to: Q,
10311031
) -> io::Result<()> {
1032-
run_path_with_wcstr(to.as_ref(), &|to| self.rename_native(from.as_ref(), to_dir, to, false))
1032+
run_path_with_utf16(to.as_ref(), &|to| self.rename_native(from.as_ref(), to_dir, to, false))
10331033
}
10341034

10351035
pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(&self, original: P, link: Q) -> io::Result<()> {
@@ -1133,58 +1133,64 @@ impl Dir {
11331133
if result == 0 { Err(api::get_last_error()).io_result() } else { Ok(()) }
11341134
}
11351135

1136-
fn rename_native(&self, from: &Path, to_dir: &Self, to: &WCStr, dir: bool) -> io::Result<()> {
1136+
fn rename_native(&self, from: &Path, to_dir: &Self, to: &[u16], dir: bool) -> io::Result<()> {
11371137
let mut opts = OpenOptions::new();
11381138
opts.access_mode(c::DELETE);
11391139
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
11401140
let handle = run_path_with_utf16(from, &|u| self.open_native(u, &opts, dir))?;
1141-
// Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation`
1141+
// Calculate the layout of the `FILE_RENAME_INFORMATION` we pass to `NtSetInformationFile`
11421142
// This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size.
11431143
const too_long_err: io::Error =
11441144
io::const_error!(io::ErrorKind::InvalidFilename, "Filename too long");
11451145
let struct_size = to
1146-
.count_bytes()
1146+
.len()
11471147
.checked_mul(2)
1148-
.and_then(|x| x.checked_add(offset_of!(c::FILE_RENAME_INFO, FileName)))
1148+
.and_then(|x| x.checked_add(offset_of!(c::FILE_RENAME_INFORMATION, FileName)))
11491149
.ok_or(too_long_err)?;
1150-
let layout = Layout::from_size_align(struct_size, align_of::<c::FILE_RENAME_INFO>())
1150+
let layout = Layout::from_size_align(struct_size, align_of::<c::FILE_RENAME_INFORMATION>())
11511151
.map_err(|_| too_long_err)?;
11521152
let struct_size = u32::try_from(struct_size).map_err(|_| too_long_err)?;
1153-
let to_byte_len_without_nul =
1154-
u32::try_from((to.count_bytes() - 1) * 2).map_err(|_| too_long_err)?;
1153+
let to_byte_len = u32::try_from(to.len() * 2).map_err(|_| too_long_err)?;
11551154

11561155
let file_rename_info;
1157-
// SAFETY: We allocate enough memory for a full FILE_RENAME_INFO struct and a filename.
1156+
// SAFETY: We allocate enough memory for a full FILE_RENAME_INFORMATION struct and the filename.
11581157
unsafe {
1159-
file_rename_info = alloc(layout).cast::<c::FILE_RENAME_INFO>();
1158+
file_rename_info = alloc(layout).cast::<c::FILE_RENAME_INFORMATION>();
11601159
if file_rename_info.is_null() {
11611160
return Err(io::ErrorKind::OutOfMemory.into());
11621161
}
11631162

1164-
(&raw mut (*file_rename_info).Anonymous).write(c::FILE_RENAME_INFO_0 {
1163+
(&raw mut (*file_rename_info).Anonymous).write(c::FILE_RENAME_INFORMATION_0 {
11651164
Flags: c::FILE_RENAME_FLAG_REPLACE_IF_EXISTS | c::FILE_RENAME_FLAG_POSIX_SEMANTICS,
11661165
});
11671166

11681167
(&raw mut (*file_rename_info).RootDirectory).write(to_dir.handle.as_raw_handle());
11691168
// Don't include the NULL in the size
1170-
(&raw mut (*file_rename_info).FileNameLength).write(to_byte_len_without_nul);
1169+
(&raw mut (*file_rename_info).FileNameLength).write(to_byte_len);
11711170

11721171
to.as_ptr().copy_to_nonoverlapping(
11731172
(&raw mut (*file_rename_info).FileName).cast::<u16>(),
1174-
to.count_bytes(),
1173+
to.len(),
11751174
);
11761175
}
11771176

1178-
let result = unsafe {
1179-
c::SetFileInformationByHandle(
1177+
let status = unsafe {
1178+
c::NtSetInformationFile(
11801179
handle.as_raw_handle(),
1181-
c::FileRenameInfoEx,
1180+
&mut c::IO_STATUS_BLOCK::default(),
11821181
file_rename_info.cast::<c_void>(),
11831182
struct_size,
1183+
c::FileRenameInformation,
11841184
)
11851185
};
11861186
unsafe { dealloc(file_rename_info.cast::<u8>(), layout) };
1187-
if result == 0 { Err(api::get_last_error()).io_result() } else { Ok(()) }
1187+
if c::nt_success(status) {
1188+
// SAFETY: nt_success guarantees that handle is no longer null
1189+
Ok(())
1190+
} else {
1191+
Err(WinError::new(unsafe { c::RtlNtStatusToDosError(status) }))
1192+
}
1193+
.io_result()
11881194
}
11891195

11901196
fn symlink_native(&self, original: &[u16], link: &Path, relative: bool) -> io::Result<()> {

library/std/src/sys/pal/windows/c/bindings.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,6 +2067,7 @@ FILE_READ_EA
20672067
FILE_RENAME_FLAG_POSIX_SEMANTICS
20682068
FILE_RENAME_FLAG_REPLACE_IF_EXISTS
20692069
FILE_RENAME_INFO
2070+
FILE_RENAME_INFORMATION
20702071
FILE_RESERVE_OPFILTER
20712072
FILE_SEQUENTIAL_ONLY
20722073
FILE_SESSION_AWARE
@@ -2112,6 +2113,8 @@ FileNormalizedNameInfo
21122113
FileRemoteProtocolInfo
21132114
FileRenameInfo
21142115
FileRenameInfoEx
2116+
FileRenameInformation
2117+
FileRenameInformationEx
21152118
FileStandardInfo
21162119
FileStorageInfo
21172120
FileStreamInfo
@@ -2292,6 +2295,7 @@ NTCREATEFILE_CREATE_DISPOSITION
22922295
NTCREATEFILE_CREATE_OPTIONS
22932296
NtOpenFile
22942297
NtReadFile
2298+
NtSetInformationFile
22952299
NTSTATUS
22962300
NtWriteFile
22972301
OBJ_DONT_REPARSE

library/std/src/sys/pal/windows/c/windows_sys.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ windows_targets::link!("kernel32.dll" "system" fn MultiByteToWideChar(codepage :
7373
windows_targets::link!("ntdll.dll" "system" fn NtCreateFile(filehandle : *mut HANDLE, desiredaccess : FILE_ACCESS_RIGHTS, objectattributes : *const OBJECT_ATTRIBUTES, iostatusblock : *mut IO_STATUS_BLOCK, allocationsize : *const i64, fileattributes : FILE_FLAGS_AND_ATTRIBUTES, shareaccess : FILE_SHARE_MODE, createdisposition : NTCREATEFILE_CREATE_DISPOSITION, createoptions : NTCREATEFILE_CREATE_OPTIONS, eabuffer : *const core::ffi::c_void, ealength : u32) -> NTSTATUS);
7474
windows_targets::link!("ntdll.dll" "system" fn NtOpenFile(filehandle : *mut HANDLE, desiredaccess : u32, objectattributes : *const OBJECT_ATTRIBUTES, iostatusblock : *mut IO_STATUS_BLOCK, shareaccess : u32, openoptions : u32) -> NTSTATUS);
7575
windows_targets::link!("ntdll.dll" "system" fn NtReadFile(filehandle : HANDLE, event : HANDLE, apcroutine : PIO_APC_ROUTINE, apccontext : *const core::ffi::c_void, iostatusblock : *mut IO_STATUS_BLOCK, buffer : *mut core::ffi::c_void, length : u32, byteoffset : *const i64, key : *const u32) -> NTSTATUS);
76+
windows_targets::link!("ntdll.dll" "system" fn NtSetInformationFile(filehandle : HANDLE, iostatusblock : *mut IO_STATUS_BLOCK, fileinformation : *const core::ffi::c_void, length : u32, fileinformationclass : FILE_INFORMATION_CLASS) -> NTSTATUS);
7677
windows_targets::link!("ntdll.dll" "system" fn NtWriteFile(filehandle : HANDLE, event : HANDLE, apcroutine : PIO_APC_ROUTINE, apccontext : *const core::ffi::c_void, iostatusblock : *mut IO_STATUS_BLOCK, buffer : *const core::ffi::c_void, length : u32, byteoffset : *const i64, key : *const u32) -> NTSTATUS);
7778
windows_targets::link!("advapi32.dll" "system" fn OpenProcessToken(processhandle : HANDLE, desiredaccess : TOKEN_ACCESS_MASK, tokenhandle : *mut HANDLE) -> BOOL);
7879
windows_targets::link!("kernel32.dll" "system" fn QueryPerformanceCounter(lpperformancecount : *mut i64) -> BOOL);
@@ -2529,6 +2530,7 @@ impl Default for FILE_ID_BOTH_DIR_INFO {
25292530
unsafe { core::mem::zeroed() }
25302531
}
25312532
}
2533+
pub type FILE_INFORMATION_CLASS = i32;
25322534
pub type FILE_INFO_BY_HANDLE_CLASS = i32;
25332535
#[repr(C)]
25342536
#[derive(Clone, Copy, Default)]
@@ -2582,6 +2584,30 @@ impl Default for FILE_RENAME_INFO_0 {
25822584
unsafe { core::mem::zeroed() }
25832585
}
25842586
}
2587+
#[repr(C)]
2588+
#[derive(Clone, Copy)]
2589+
pub struct FILE_RENAME_INFORMATION {
2590+
pub Anonymous: FILE_RENAME_INFORMATION_0,
2591+
pub RootDirectory: HANDLE,
2592+
pub FileNameLength: u32,
2593+
pub FileName: [u16; 1],
2594+
}
2595+
impl Default for FILE_RENAME_INFORMATION {
2596+
fn default() -> Self {
2597+
unsafe { core::mem::zeroed() }
2598+
}
2599+
}
2600+
#[repr(C)]
2601+
#[derive(Clone, Copy)]
2602+
pub union FILE_RENAME_INFORMATION_0 {
2603+
pub ReplaceIfExists: bool,
2604+
pub Flags: u32,
2605+
}
2606+
impl Default for FILE_RENAME_INFORMATION_0 {
2607+
fn default() -> Self {
2608+
unsafe { core::mem::zeroed() }
2609+
}
2610+
}
25852611
pub const FILE_RESERVE_OPFILTER: NTCREATEFILE_CREATE_OPTIONS = 1048576u32;
25862612
pub const FILE_SEQUENTIAL_ONLY: NTCREATEFILE_CREATE_OPTIONS = 4u32;
25872613
pub const FILE_SESSION_AWARE: NTCREATEFILE_CREATE_OPTIONS = 262144u32;
@@ -2689,6 +2715,8 @@ pub const FileNormalizedNameInfo: FILE_INFO_BY_HANDLE_CLASS = 24i32;
26892715
pub const FileRemoteProtocolInfo: FILE_INFO_BY_HANDLE_CLASS = 13i32;
26902716
pub const FileRenameInfo: FILE_INFO_BY_HANDLE_CLASS = 3i32;
26912717
pub const FileRenameInfoEx: FILE_INFO_BY_HANDLE_CLASS = 22i32;
2718+
pub const FileRenameInformation: FILE_INFORMATION_CLASS = 10i32;
2719+
pub const FileRenameInformationEx: FILE_INFORMATION_CLASS = 65i32;
26922720
pub const FileStandardInfo: FILE_INFO_BY_HANDLE_CLASS = 1i32;
26932721
pub const FileStorageInfo: FILE_INFO_BY_HANDLE_CLASS = 16i32;
26942722
pub const FileStreamInfo: FILE_INFO_BY_HANDLE_CLASS = 7i32;

0 commit comments

Comments
 (0)