Skip to content

Commit 5951166

Browse files
committed
change rename implementation
1 parent a7bc6c3 commit 5951166

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
@@ -1035,7 +1035,7 @@ impl Dir {
10351035
to_dir: &Self,
10361036
to: Q,
10371037
) -> io::Result<()> {
1038-
run_path_with_wcstr(to.as_ref(), &|to| self.rename_native(from.as_ref(), to_dir, to, false))
1038+
run_path_with_utf16(to.as_ref(), &|to| self.rename_native(from.as_ref(), to_dir, to, false))
10391039
}
10401040

10411041
pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(&self, original: P, link: Q) -> io::Result<()> {
@@ -1139,58 +1139,64 @@ impl Dir {
11391139
if result == 0 { Err(api::get_last_error()).io_result() } else { Ok(()) }
11401140
}
11411141

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

11621161
let file_rename_info;
1163-
// SAFETY: We allocate enough memory for a full FILE_RENAME_INFO struct and a filename.
1162+
// SAFETY: We allocate enough memory for a full FILE_RENAME_INFORMATION struct and the filename.
11641163
unsafe {
1165-
file_rename_info = alloc(layout).cast::<c::FILE_RENAME_INFO>();
1164+
file_rename_info = alloc(layout).cast::<c::FILE_RENAME_INFORMATION>();
11661165
if file_rename_info.is_null() {
11671166
return Err(io::ErrorKind::OutOfMemory.into());
11681167
}
11691168

1170-
(&raw mut (*file_rename_info).Anonymous).write(c::FILE_RENAME_INFO_0 {
1169+
(&raw mut (*file_rename_info).Anonymous).write(c::FILE_RENAME_INFORMATION_0 {
11711170
Flags: c::FILE_RENAME_FLAG_REPLACE_IF_EXISTS | c::FILE_RENAME_FLAG_POSIX_SEMANTICS,
11721171
});
11731172

11741173
(&raw mut (*file_rename_info).RootDirectory).write(to_dir.handle.as_raw_handle());
11751174
// Don't include the NULL in the size
1176-
(&raw mut (*file_rename_info).FileNameLength).write(to_byte_len_without_nul);
1175+
(&raw mut (*file_rename_info).FileNameLength).write(to_byte_len);
11771176

11781177
to.as_ptr().copy_to_nonoverlapping(
11791178
(&raw mut (*file_rename_info).FileName).cast::<u16>(),
1180-
to.count_bytes(),
1179+
to.len(),
11811180
);
11821181
}
11831182

1184-
let result = unsafe {
1185-
c::SetFileInformationByHandle(
1183+
let status = unsafe {
1184+
c::NtSetInformationFile(
11861185
handle.as_raw_handle(),
1187-
c::FileRenameInfoEx,
1186+
&mut c::IO_STATUS_BLOCK::default(),
11881187
file_rename_info.cast::<c_void>(),
11891188
struct_size,
1189+
c::FileRenameInformation,
11901190
)
11911191
};
11921192
unsafe { dealloc(file_rename_info.cast::<u8>(), layout) };
1193-
if result == 0 { Err(api::get_last_error()).io_result() } else { Ok(()) }
1193+
if c::nt_success(status) {
1194+
// SAFETY: nt_success guarantees that handle is no longer null
1195+
Ok(())
1196+
} else {
1197+
Err(WinError::new(unsafe { c::RtlNtStatusToDosError(status) }))
1198+
}
1199+
.io_result()
11941200
}
11951201

11961202
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
@@ -2301,6 +2304,7 @@ NTCREATEFILE_CREATE_DISPOSITION
23012304
NTCREATEFILE_CREATE_OPTIONS
23022305
NtOpenFile
23032306
NtReadFile
2307+
NtSetInformationFile
23042308
NTSTATUS
23052309
NtWriteFile
23062310
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
@@ -74,6 +74,7 @@ windows_targets::link!("kernel32.dll" "system" fn MultiByteToWideChar(codepage :
7474
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);
7575
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);
7676
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);
77+
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);
7778
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);
7879
windows_targets::link!("advapi32.dll" "system" fn OpenProcessToken(processhandle : HANDLE, desiredaccess : TOKEN_ACCESS_MASK, tokenhandle : *mut HANDLE) -> BOOL);
7980
windows_targets::link!("kernel32.dll" "system" fn QueryPerformanceCounter(lpperformancecount : *mut i64) -> BOOL);
@@ -2530,6 +2531,7 @@ impl Default for FILE_ID_BOTH_DIR_INFO {
25302531
unsafe { core::mem::zeroed() }
25312532
}
25322533
}
2534+
pub type FILE_INFORMATION_CLASS = i32;
25332535
pub type FILE_INFO_BY_HANDLE_CLASS = i32;
25342536
#[repr(C)]
25352537
#[derive(Clone, Copy, Default)]
@@ -2591,6 +2593,30 @@ impl Default for FILE_RENAME_INFO_0 {
25912593
unsafe { core::mem::zeroed() }
25922594
}
25932595
}
2596+
#[repr(C)]
2597+
#[derive(Clone, Copy)]
2598+
pub struct FILE_RENAME_INFORMATION {
2599+
pub Anonymous: FILE_RENAME_INFORMATION_0,
2600+
pub RootDirectory: HANDLE,
2601+
pub FileNameLength: u32,
2602+
pub FileName: [u16; 1],
2603+
}
2604+
impl Default for FILE_RENAME_INFORMATION {
2605+
fn default() -> Self {
2606+
unsafe { core::mem::zeroed() }
2607+
}
2608+
}
2609+
#[repr(C)]
2610+
#[derive(Clone, Copy)]
2611+
pub union FILE_RENAME_INFORMATION_0 {
2612+
pub ReplaceIfExists: bool,
2613+
pub Flags: u32,
2614+
}
2615+
impl Default for FILE_RENAME_INFORMATION_0 {
2616+
fn default() -> Self {
2617+
unsafe { core::mem::zeroed() }
2618+
}
2619+
}
25942620
pub const FILE_RESERVE_OPFILTER: NTCREATEFILE_CREATE_OPTIONS = 1048576u32;
25952621
pub const FILE_SEQUENTIAL_ONLY: NTCREATEFILE_CREATE_OPTIONS = 4u32;
25962622
pub const FILE_SESSION_AWARE: NTCREATEFILE_CREATE_OPTIONS = 262144u32;
@@ -2698,6 +2724,8 @@ pub const FileNormalizedNameInfo: FILE_INFO_BY_HANDLE_CLASS = 24i32;
26982724
pub const FileRemoteProtocolInfo: FILE_INFO_BY_HANDLE_CLASS = 13i32;
26992725
pub const FileRenameInfo: FILE_INFO_BY_HANDLE_CLASS = 3i32;
27002726
pub const FileRenameInfoEx: FILE_INFO_BY_HANDLE_CLASS = 22i32;
2727+
pub const FileRenameInformation: FILE_INFORMATION_CLASS = 10i32;
2728+
pub const FileRenameInformationEx: FILE_INFORMATION_CLASS = 65i32;
27012729
pub const FileStandardInfo: FILE_INFO_BY_HANDLE_CLASS = 1i32;
27022730
pub const FileStorageInfo: FILE_INFO_BY_HANDLE_CLASS = 16i32;
27032731
pub const FileStreamInfo: FILE_INFO_BY_HANDLE_CLASS = 7i32;

0 commit comments

Comments
 (0)