Skip to content

Commit 057720e

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 9544927 commit 057720e

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
@@ -1526,6 +1526,7 @@ fn get_path(f: &File) -> io::Result<PathBuf> {
15261526
)
15271527
}
15281528

1529+
#[cfg(not(target_vendor = "rust9x"))]
15291530
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
15301531
let mut opts = OpenOptions::new();
15311532
// No read or write permissions are necessary
@@ -1536,6 +1537,28 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
15361537
get_path(&f)
15371538
}
15381539

1540+
#[cfg(target_vendor = "rust9x")]
1541+
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
1542+
if c::GetFinalPathNameByHandleW::available().is_some() {
1543+
let mut opts = OpenOptions::new();
1544+
// No read or write permissions are necessary
1545+
opts.access_mode(0);
1546+
// This flag is so we can open directories too
1547+
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
1548+
let f = File::open(p, &opts)?;
1549+
get_path(&f)
1550+
} else {
1551+
// systems that don't support GetFinalPathNameByHandleW also don't support symlinks, so we
1552+
// fall back to using GetFullPathName.
1553+
let path = maybe_verbatim(p)?;
1554+
let mut file_part = ptr::null_mut();
1555+
super::fill_utf16_buf(
1556+
|buf, sz| unsafe { c::GetFullPathNameW(path.as_ptr(), sz, buf, &mut file_part) },
1557+
|buf| PathBuf::from(OsString::from_wide(buf)),
1558+
)
1559+
}
1560+
}
1561+
15391562
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
15401563
unsafe extern "system" fn callback(
15411564
_TotalFileSize: i64,

0 commit comments

Comments
 (0)