Skip to content

Commit 759c759

Browse files
committed
Fallbacks for CreateSymbolicLinkW, CreateHardLinkW, GetFinalPathNameByHandleW
- `CreateSymbolicLinkW` is used in `std::fs::soft_link`. Fails on unsupported systems. - `CreateHardLinkW` is used in `std::fs::hard_link`. Fails on unsupported systems. - `GetFinalPathNameByHandleW` is used in `std::fs::canonicalize`. Systems that don't support `GetFinalPathNameByHandleW` also don't support symlinks, so the fallback uses `GetFullPathNameW` instead.
1 parent b69a464 commit 759c759

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,3 +445,38 @@ compat_fn_with_fallback! {
445445
FALSE
446446
}
447447
}
448+
449+
#[cfg(target_vendor = "rust9x")]
450+
compat_fn_with_fallback! {
451+
pub static KERNEL32: &CStr = c"kernel32" => { load: false, unicows: false };
452+
// >= Vista / Server 2008
453+
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
454+
pub fn CreateSymbolicLinkW(
455+
lpsymlinkfilename: PCWSTR,
456+
lptargetfilename: PCWSTR,
457+
dwflags: SYMBOLIC_LINK_FLAGS,
458+
) -> BOOLEAN {
459+
unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as u32); };
460+
0
461+
}
462+
// >= Vista / Server 2008
463+
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
464+
pub fn GetFinalPathNameByHandleW(
465+
hfile: HANDLE,
466+
lpszfilepath: PWSTR,
467+
cchfilepath: u32,
468+
dwflags: GETFINALPATHNAMEBYHANDLE_FLAGS
469+
) -> u32 {
470+
rtabort!("unimplemented")
471+
}
472+
// >= 2000
473+
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createhardlinkw
474+
pub fn CreateHardLinkW(
475+
lpfilename: PCWSTR,
476+
lpexistingfilename: PCWSTR,
477+
lpsecurityattributes: *const SECURITY_ATTRIBUTES,
478+
) -> BOOL {
479+
unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as u32); };
480+
FALSE
481+
}
482+
}

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,7 @@ fn get_path(f: &File) -> io::Result<PathBuf> {
15911591
)
15921592
}
15931593

1594+
#[cfg(not(target_vendor = "rust9x"))]
15941595
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
15951596
let mut opts = OpenOptions::new();
15961597
// No read or write permissions are necessary
@@ -1601,6 +1602,28 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
16011602
get_path(&f)
16021603
}
16031604

1605+
#[cfg(target_vendor = "rust9x")]
1606+
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
1607+
if c::GetFinalPathNameByHandleW::available().is_some() {
1608+
let mut opts = OpenOptions::new();
1609+
// No read or write permissions are necessary
1610+
opts.access_mode(0);
1611+
// This flag is so we can open directories too
1612+
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
1613+
let f = File::open(p, &opts)?;
1614+
get_path(&f)
1615+
} else {
1616+
// systems that don't support GetFinalPathNameByHandleW also don't support symlinks, so we
1617+
// fall back to using GetFullPathName.
1618+
let path = maybe_verbatim(p)?;
1619+
let mut file_part = ptr::null_mut();
1620+
super::fill_utf16_buf(
1621+
|buf, sz| unsafe { c::GetFullPathNameW(path.as_ptr(), sz, buf, &mut file_part) },
1622+
|buf| PathBuf::from(OsString::from_wide(buf)),
1623+
)
1624+
}
1625+
}
1626+
16041627
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
16051628
unsafe extern "system" fn callback(
16061629
_TotalFileSize: i64,

0 commit comments

Comments
 (0)