Skip to content

Commit 55cc76a

Browse files
committed
change rename implementation
1 parent be60aa1 commit 55cc76a

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
@@ -1030,7 +1030,7 @@ impl Dir {
10301030
to_dir: &Self,
10311031
to: Q,
10321032
) -> io::Result<()> {
1033-
run_path_with_wcstr(to.as_ref(), &|to| self.rename_native(from.as_ref(), to_dir, to, false))
1033+
run_path_with_utf16(to.as_ref(), &|to| self.rename_native(from.as_ref(), to_dir, to, false))
10341034
}
10351035

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

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

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

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

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

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

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

11911197
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
@@ -2075,6 +2075,7 @@ FILE_READ_EA
20752075
FILE_RENAME_FLAG_POSIX_SEMANTICS
20762076
FILE_RENAME_FLAG_REPLACE_IF_EXISTS
20772077
FILE_RENAME_INFO
2078+
FILE_RENAME_INFORMATION
20782079
FILE_RESERVE_OPFILTER
20792080
FILE_SEQUENTIAL_ONLY
20802081
FILE_SESSION_AWARE
@@ -2120,6 +2121,8 @@ FileNormalizedNameInfo
21202121
FileRemoteProtocolInfo
21212122
FileRenameInfo
21222123
FileRenameInfoEx
2124+
FileRenameInformation
2125+
FileRenameInformationEx
21232126
FileStandardInfo
21242127
FileStorageInfo
21252128
FileStreamInfo
@@ -2300,6 +2303,7 @@ NTCREATEFILE_CREATE_DISPOSITION
23002303
NTCREATEFILE_CREATE_OPTIONS
23012304
NtOpenFile
23022305
NtReadFile
2306+
NtSetInformationFile
23032307
NTSTATUS
23042308
NtWriteFile
23052309
OBJ_CASE_INSENSITIVE

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)]
@@ -2590,6 +2592,30 @@ impl Default for FILE_RENAME_INFO_0 {
25902592
unsafe { core::mem::zeroed() }
25912593
}
25922594
}
2595+
#[repr(C)]
2596+
#[derive(Clone, Copy)]
2597+
pub struct FILE_RENAME_INFORMATION {
2598+
pub Anonymous: FILE_RENAME_INFORMATION_0,
2599+
pub RootDirectory: HANDLE,
2600+
pub FileNameLength: u32,
2601+
pub FileName: [u16; 1],
2602+
}
2603+
impl Default for FILE_RENAME_INFORMATION {
2604+
fn default() -> Self {
2605+
unsafe { core::mem::zeroed() }
2606+
}
2607+
}
2608+
#[repr(C)]
2609+
#[derive(Clone, Copy)]
2610+
pub union FILE_RENAME_INFORMATION_0 {
2611+
pub ReplaceIfExists: bool,
2612+
pub Flags: u32,
2613+
}
2614+
impl Default for FILE_RENAME_INFORMATION_0 {
2615+
fn default() -> Self {
2616+
unsafe { core::mem::zeroed() }
2617+
}
2618+
}
25932619
pub const FILE_RESERVE_OPFILTER: NTCREATEFILE_CREATE_OPTIONS = 1048576u32;
25942620
pub const FILE_SEQUENTIAL_ONLY: NTCREATEFILE_CREATE_OPTIONS = 4u32;
25952621
pub const FILE_SESSION_AWARE: NTCREATEFILE_CREATE_OPTIONS = 262144u32;
@@ -2697,6 +2723,8 @@ pub const FileNormalizedNameInfo: FILE_INFO_BY_HANDLE_CLASS = 24i32;
26972723
pub const FileRemoteProtocolInfo: FILE_INFO_BY_HANDLE_CLASS = 13i32;
26982724
pub const FileRenameInfo: FILE_INFO_BY_HANDLE_CLASS = 3i32;
26992725
pub const FileRenameInfoEx: FILE_INFO_BY_HANDLE_CLASS = 22i32;
2726+
pub const FileRenameInformation: FILE_INFORMATION_CLASS = 10i32;
2727+
pub const FileRenameInformationEx: FILE_INFORMATION_CLASS = 65i32;
27002728
pub const FileStandardInfo: FILE_INFO_BY_HANDLE_CLASS = 1i32;
27012729
pub const FileStorageInfo: FILE_INFO_BY_HANDLE_CLASS = 16i32;
27022730
pub const FileStreamInfo: FILE_INFO_BY_HANDLE_CLASS = 7i32;

0 commit comments

Comments
 (0)