1use std::path::Path;
2
3#[cfg(windows)]
4#[allow(unsafe_code)] fn get_binary_type(path: &Path) -> windows::core::Result<u32> {
6 use std::os::windows::ffi::OsStrExt;
7 use windows::Win32::Storage::FileSystem::GetBinaryTypeW;
8 use windows::core::PCWSTR;
9
10 let mut binary_type = 0u32;
14 let name = path
15 .as_os_str()
16 .encode_wide()
17 .chain(Some(0))
18 .collect::<Vec<u16>>();
19 unsafe { GetBinaryTypeW(PCWSTR(name.as_ptr()), &raw mut binary_type)? };
21 Ok(binary_type)
22}
23
24pub fn is_executable(path: &Path) -> bool {
28 #[cfg(any(unix, target_os = "wasi", target_os = "redox"))]
29 {
30 if rustix::fs::access(path, rustix::fs::Access::EXEC_OK).is_err() {
31 return false;
32 }
33 }
34
35 #[cfg(target_os = "windows")]
36 {
37 let Ok(file_type) = fs_err::symlink_metadata(path).map(|metadata| metadata.file_type())
38 else {
39 return false;
40 };
41 if !file_type.is_file() && !file_type.is_symlink() {
42 return false;
43 }
44 if path.extension().is_none() && get_binary_type(path).is_err() {
45 return false;
46 }
47 }
48
49 #[cfg(not(target_os = "windows"))]
50 {
51 use std::os::unix::fs::PermissionsExt;
52
53 if !fs_err::metadata(path)
54 .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)
55 .unwrap_or(false)
56 {
57 return false;
58 }
59 }
60
61 true
62}