blob: 638beb00b90b7aeaf57dcaa8b9f611d779cc511b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
//! Shared helpers for integration tests.
use std::path::Path;
/// Windows refuses file symlinks with `ERROR_PRIVILEGE_NOT_HELD` when the
/// process is neither elevated nor running with Developer Mode enabled.
#[cfg(windows)]
const ERROR_PRIVILEGE_NOT_HELD: i32 = 1314;
#[cfg(windows)]
fn symlink_privilege_denied(error: &std::io::Error) -> bool {
error.raw_os_error() == Some(ERROR_PRIVILEGE_NOT_HELD)
}
/// Create a file symlink, returning `false` when Windows denied the symlink
/// privilege. Callers skip symlink-only assertions on `false` instead of
/// failing an ordinary non-elevated local test run.
#[cfg(unix)]
pub(super) fn symlink_file(target: &Path, link: &Path) -> bool {
std::os::unix::fs::symlink(target, link).expect("create symlink");
true
}
#[cfg(windows)]
pub(super) fn symlink_file(target: &Path, link: &Path) -> bool {
match std::os::windows::fs::symlink_file(target, link) {
Ok(()) => true,
Err(error) if symlink_privilege_denied(&error) => {
eprintln!("skipping symlink test: Windows denied SeCreateSymbolicLinkPrivilege");
false
}
Err(error) => panic!("create symlink {}: {error}", link.display()),
}
}
#[cfg(all(test, windows))]
mod tests {
use super::*;
#[test]
fn symlink_privilege_error_is_detected() {
assert!(symlink_privilege_denied(
&std::io::Error::from_raw_os_error(ERROR_PRIVILEGE_NOT_HELD)
));
assert!(!symlink_privilege_denied(
&std::io::Error::from_raw_os_error(/* ERROR_ACCESS_DENIED */ 5)
));
}
}
|