Skip to content

Commit e43dc76

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 95c805f commit e43dc76

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

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

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

1448+
#[cfg(not(target_vendor = "rust9x"))]
14481449
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
14491450
let mut opts = OpenOptions::new();
14501451
// No read or write permissions are necessary
@@ -1455,6 +1456,28 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
14551456
get_path(&f)
14561457
}
14571458

1459+
#[cfg(target_vendor = "rust9x")]
1460+
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
1461+
if c::GetFinalPathNameByHandleW::available().is_some() {
1462+
let mut opts = OpenOptions::new();
1463+
// No read or write permissions are necessary
1464+
opts.access_mode(0);
1465+
// This flag is so we can open directories too
1466+
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
1467+
let f = File::open(p, &opts)?;
1468+
get_path(&f)
1469+
} else {
1470+
// systems that don't support GetFinalPathNameByHandleW also don't support symlinks, so we
1471+
// fall back to using GetFullPathName.
1472+
let path = maybe_verbatim(p)?;
1473+
let mut file_part = ptr::null_mut();
1474+
super::fill_utf16_buf(
1475+
|buf, sz| unsafe { c::GetFullPathNameW(path.as_ptr(), sz, buf, &mut file_part) },
1476+
|buf| PathBuf::from(OsString::from_wide(buf)),
1477+
)
1478+
}
1479+
}
1480+
14581481
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
14591482
unsafe extern "system" fn callback(
14601483
_TotalFileSize: i64,

0 commit comments

Comments
 (0)