mirror of
https://github.com/denoland/deno.git
synced 2025-10-02 23:24:37 +00:00
refactor: allow deno_permissions to compile to wasm32-unknown-unknown (#29487)
Some checks are pending
ci / pre-build (push) Waiting to run
ci / test debug linux-aarch64 (push) Blocked by required conditions
ci / test release linux-aarch64 (push) Blocked by required conditions
ci / test debug macos-aarch64 (push) Blocked by required conditions
ci / test release macos-aarch64 (push) Blocked by required conditions
ci / bench release linux-x86_64 (push) Blocked by required conditions
ci / lint debug linux-x86_64 (push) Blocked by required conditions
ci / lint debug macos-x86_64 (push) Blocked by required conditions
ci / lint debug windows-x86_64 (push) Blocked by required conditions
ci / test debug linux-x86_64 (push) Blocked by required conditions
ci / test release linux-x86_64 (push) Blocked by required conditions
ci / test debug macos-x86_64 (push) Blocked by required conditions
ci / test release macos-x86_64 (push) Blocked by required conditions
ci / test debug windows-x86_64 (push) Blocked by required conditions
ci / test release windows-x86_64 (push) Blocked by required conditions
ci / build wasm32 (push) Blocked by required conditions
ci / publish canary (push) Blocked by required conditions
Some checks are pending
ci / pre-build (push) Waiting to run
ci / test debug linux-aarch64 (push) Blocked by required conditions
ci / test release linux-aarch64 (push) Blocked by required conditions
ci / test debug macos-aarch64 (push) Blocked by required conditions
ci / test release macos-aarch64 (push) Blocked by required conditions
ci / bench release linux-x86_64 (push) Blocked by required conditions
ci / lint debug linux-x86_64 (push) Blocked by required conditions
ci / lint debug macos-x86_64 (push) Blocked by required conditions
ci / lint debug windows-x86_64 (push) Blocked by required conditions
ci / test debug linux-x86_64 (push) Blocked by required conditions
ci / test release linux-x86_64 (push) Blocked by required conditions
ci / test debug macos-x86_64 (push) Blocked by required conditions
ci / test release macos-x86_64 (push) Blocked by required conditions
ci / test debug windows-x86_64 (push) Blocked by required conditions
ci / test release windows-x86_64 (push) Blocked by required conditions
ci / build wasm32 (push) Blocked by required conditions
ci / publish canary (push) Blocked by required conditions
This commit is contained in:
parent
437afebf5c
commit
cb23193f74
17 changed files with 411 additions and 106 deletions
|
@ -22,12 +22,12 @@ use deno_permissions::WriteDescriptor;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct RuntimePermissionDescriptorParser<
|
||||
TSys: sys_traits::EnvCurrentDir + Send + Sync,
|
||||
TSys: deno_permissions::which::WhichSys + Send + Sync,
|
||||
> {
|
||||
sys: TSys,
|
||||
}
|
||||
|
||||
impl<TSys: sys_traits::EnvCurrentDir + Send + Sync>
|
||||
impl<TSys: deno_permissions::which::WhichSys + Send + Sync>
|
||||
RuntimePermissionDescriptorParser<TSys>
|
||||
{
|
||||
pub fn new(sys: TSys) -> Self {
|
||||
|
@ -55,7 +55,7 @@ impl<TSys: sys_traits::EnvCurrentDir + Send + Sync>
|
|||
}
|
||||
}
|
||||
|
||||
impl<TSys: sys_traits::EnvCurrentDir + Send + Sync + std::fmt::Debug>
|
||||
impl<TSys: deno_permissions::which::WhichSys + Send + Sync + std::fmt::Debug>
|
||||
deno_permissions::PermissionDescriptorParser
|
||||
for RuntimePermissionDescriptorParser<TSys>
|
||||
{
|
||||
|
@ -113,7 +113,11 @@ impl<TSys: sys_traits::EnvCurrentDir + Send + Sync + std::fmt::Debug>
|
|||
&self,
|
||||
text: &str,
|
||||
) -> Result<AllowRunDescriptorParseResult, RunDescriptorParseError> {
|
||||
Ok(AllowRunDescriptor::parse(text, &self.resolve_cwd()?)?)
|
||||
Ok(AllowRunDescriptor::parse(
|
||||
text,
|
||||
&self.resolve_cwd()?,
|
||||
&self.sys,
|
||||
)?)
|
||||
}
|
||||
|
||||
fn parse_deny_run_descriptor(
|
||||
|
@ -149,7 +153,7 @@ impl<TSys: sys_traits::EnvCurrentDir + Send + Sync + std::fmt::Debug>
|
|||
if requested.is_empty() {
|
||||
return Err(RunDescriptorParseError::EmptyRunQuery);
|
||||
}
|
||||
RunQueryDescriptor::parse(requested)
|
||||
RunQueryDescriptor::parse(requested, &self.sys)
|
||||
.map_err(RunDescriptorParseError::PathResolve)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,17 @@ parking_lot.workspace = true
|
|||
percent-encoding = { workspace = true, features = [] }
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
sys_traits.workspace = true
|
||||
temp_deno_which.workspace = true
|
||||
thiserror.workspace = true
|
||||
url.workspace = true
|
||||
which.workspace = true
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { workspace = true, features = ["commapi", "knownfolders", "mswsock", "objbase", "psapi", "shlobj", "tlhelp32", "winbase", "winerror", "winuser", "winsock2", "processenv", "wincon", "wincontypes"] }
|
||||
windows-sys = { workspace = true, features = ["Win32_Storage_FileSystem"] }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
nix = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
sys_traits = { workspace = true, features = ["real"] }
|
||||
|
|
|
@ -1,3 +1,49 @@
|
|||
disallowed-methods = [
|
||||
{ path = "std::str::FromStr", reason = "Don't want to have stuff like `'0.0.0.0'.parse().unwrap()`. Instead implement ConcreteType::parse methods." },
|
||||
{ path = "std::env::current_dir", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::canonicalize", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::is_dir", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::is_file", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::is_symlink", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::metadata", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::read_dir", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::read_link", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::symlink_metadata", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::try_exists", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::PathBuf::exists", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::PathBuf::canonicalize", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::PathBuf::is_dir", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::PathBuf::is_file", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::PathBuf::is_symlink", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::PathBuf::metadata", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::PathBuf::read_dir", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::PathBuf::read_link", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::PathBuf::symlink_metadata", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::PathBuf::try_exists", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::env::set_current_dir", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::env::temp_dir", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::canonicalize", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::copy", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::create_dir_all", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::create_dir", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::DirBuilder::new", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::hard_link", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::metadata", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::OpenOptions::new", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::read_dir", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::read_link", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::read_to_string", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::read", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::remove_dir_all", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::remove_dir", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::remove_file", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::rename", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::set_permissions", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::symlink_metadata", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::fs::write", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::canonicalize", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "std::path::Path::exists", reason = "File system operations should be done using sys_traits" },
|
||||
{ path = "url::Url::to_file_path", reason = "Use deno_path_util instead so it works in Wasm" },
|
||||
{ path = "url::Url::from_file_path", reason = "Use deno_path_util instead so it works in Wasm" },
|
||||
{ path = "url::Url::from_directory_path", reason = "Use deno_path_util instead so it works in Wasm" },
|
||||
]
|
||||
|
|
|
@ -28,15 +28,19 @@ use serde::Serialize;
|
|||
use url::Url;
|
||||
|
||||
pub mod prompter;
|
||||
pub mod which;
|
||||
use prompter::permission_prompt;
|
||||
pub use prompter::set_prompt_callbacks;
|
||||
pub use prompter::set_prompter;
|
||||
pub use prompter::DeniedPrompter;
|
||||
pub use prompter::GetFormattedStackFn;
|
||||
pub use prompter::PermissionPrompter;
|
||||
pub use prompter::PromptCallback;
|
||||
pub use prompter::PromptResponse;
|
||||
use prompter::PERMISSION_EMOJI;
|
||||
|
||||
use self::which::WhichSys;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum PermissionDeniedError {
|
||||
#[error("Requires {access}, {}", format_permission_error(.name))]
|
||||
|
@ -1373,14 +1377,16 @@ pub enum PathResolveError {
|
|||
impl RunQueryDescriptor {
|
||||
pub fn parse(
|
||||
requested: &str,
|
||||
sys: &impl which::WhichSys,
|
||||
) -> Result<RunQueryDescriptor, PathResolveError> {
|
||||
if is_path(requested) {
|
||||
let path = PathBuf::from(requested);
|
||||
let resolved = if path.is_absolute() {
|
||||
normalize_path(path)
|
||||
} else {
|
||||
let cwd =
|
||||
std::env::current_dir().map_err(PathResolveError::CwdResolve)?;
|
||||
let cwd = sys
|
||||
.env_current_dir()
|
||||
.map_err(PathResolveError::CwdResolve)?;
|
||||
normalize_path(cwd.join(path))
|
||||
};
|
||||
Ok(RunQueryDescriptor::Path {
|
||||
|
@ -1388,7 +1394,11 @@ impl RunQueryDescriptor {
|
|||
resolved,
|
||||
})
|
||||
} else {
|
||||
match which::which(requested) {
|
||||
let cwd = sys
|
||||
.env_current_dir()
|
||||
.map_err(PathResolveError::CwdResolve)?;
|
||||
match which::which_in(sys.clone(), requested, sys.env_var_os("PATH"), cwd)
|
||||
{
|
||||
Ok(resolved) => Ok(RunQueryDescriptor::Path {
|
||||
requested: requested.to_string(),
|
||||
resolved,
|
||||
|
@ -1542,13 +1552,19 @@ impl AllowRunDescriptor {
|
|||
pub fn parse(
|
||||
text: &str,
|
||||
cwd: &Path,
|
||||
sys: &impl WhichSys,
|
||||
) -> Result<AllowRunDescriptorParseResult, which::Error> {
|
||||
let is_path = is_path(text);
|
||||
// todo(dsherret): canonicalize in #25458
|
||||
let path = if is_path {
|
||||
resolve_from_known_cwd(Path::new(text), cwd)
|
||||
} else {
|
||||
match which::which_in(text, std::env::var_os("PATH"), cwd) {
|
||||
match which::which_in(
|
||||
sys.clone(),
|
||||
text,
|
||||
sys.env_var_os("PATH"),
|
||||
cwd.to_path_buf(),
|
||||
) {
|
||||
Ok(path) => path,
|
||||
Err(err) => match err {
|
||||
which::Error::CannotGetCurrentDirAndPathListEmpty => {
|
||||
|
@ -3879,7 +3895,8 @@ mod tests {
|
|||
&self,
|
||||
requested: &str,
|
||||
) -> Result<RunQueryDescriptor, RunDescriptorParseError> {
|
||||
RunQueryDescriptor::parse(requested).map_err(Into::into)
|
||||
RunQueryDescriptor::parse(requested, &sys_traits::impls::RealSys)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,13 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::fmt::Write;
|
||||
use std::io::BufRead;
|
||||
use std::io::IsTerminal;
|
||||
use std::io::StderrLock;
|
||||
use std::io::StdinLock;
|
||||
use std::io::Write as IoWrite;
|
||||
|
||||
use deno_terminal::colors;
|
||||
use once_cell::sync::Lazy;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use crate::is_standalone;
|
||||
|
||||
/// Helper function to make control characters visible so users can see the underlying filename.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn escape_control_characters(s: &str) -> std::borrow::Cow<str> {
|
||||
use deno_terminal::colors;
|
||||
|
||||
if !s.contains(|c: char| c.is_ascii_control() || c.is_control()) {
|
||||
return std::borrow::Cow::Borrowed(s);
|
||||
}
|
||||
|
@ -35,9 +28,6 @@ fn escape_control_characters(s: &str) -> std::borrow::Cow<str> {
|
|||
|
||||
pub const PERMISSION_EMOJI: &str = "⚠️";
|
||||
|
||||
// 10kB of permission prompting should be enough for anyone
|
||||
const MAX_PERMISSION_PROMPT_LENGTH: usize = 10 * 1024;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum PromptResponse {
|
||||
Allow,
|
||||
|
@ -45,8 +35,13 @@ pub enum PromptResponse {
|
|||
AllowAll,
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
type DefaultPrompter = TtyPrompter;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
type DefaultPrompter = DeniedPrompter;
|
||||
|
||||
static PERMISSION_PROMPTER: Lazy<Mutex<Box<dyn PermissionPrompter>>> =
|
||||
Lazy::new(|| Mutex::new(Box::new(TtyPrompter)));
|
||||
Lazy::new(|| Mutex::new(Box::new(DefaultPrompter::default())));
|
||||
|
||||
static MAYBE_BEFORE_PROMPT_CALLBACK: Lazy<Mutex<Option<PromptCallback>>> =
|
||||
Lazy::new(|| Mutex::new(None));
|
||||
|
@ -107,12 +102,26 @@ pub trait PermissionPrompter: Send + Sync {
|
|||
) -> PromptResponse;
|
||||
}
|
||||
|
||||
pub struct TtyPrompter;
|
||||
#[derive(Default)]
|
||||
pub struct DeniedPrompter;
|
||||
|
||||
impl PermissionPrompter for DeniedPrompter {
|
||||
fn prompt(
|
||||
&mut self,
|
||||
_message: &str,
|
||||
_name: &str,
|
||||
_api_name: Option<&str>,
|
||||
_is_unary: bool,
|
||||
_get_stack: Option<GetFormattedStackFn>,
|
||||
) -> PromptResponse {
|
||||
PromptResponse::Deny
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn clear_stdin(
|
||||
_stdin_lock: &mut StdinLock,
|
||||
_stderr_lock: &mut StderrLock,
|
||||
_stdin_lock: &mut std::io::StdinLock,
|
||||
_stderr_lock: &mut std::io::StderrLock,
|
||||
) -> Result<(), std::io::Error> {
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
|
@ -163,11 +172,15 @@ fn clear_stdin(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
#[cfg(all(not(unix), not(target_arch = "wasm32")))]
|
||||
fn clear_stdin(
|
||||
stdin_lock: &mut StdinLock,
|
||||
stderr_lock: &mut StderrLock,
|
||||
stdin_lock: &mut std::io::StdinLock,
|
||||
stderr_lock: &mut std::io::StderrLock,
|
||||
) -> Result<(), std::io::Error> {
|
||||
use std::io::BufRead;
|
||||
use std::io::StdinLock;
|
||||
use std::io::Write as IoWrite;
|
||||
|
||||
use winapi::shared::minwindef::TRUE;
|
||||
use winapi::shared::minwindef::UINT;
|
||||
use winapi::shared::minwindef::WORD;
|
||||
|
@ -257,7 +270,7 @@ fn clear_stdin(
|
|||
}
|
||||
|
||||
fn move_cursor_up(
|
||||
stderr_lock: &mut StderrLock,
|
||||
stderr_lock: &mut std::io::StderrLock,
|
||||
) -> Result<(), std::io::Error> {
|
||||
write!(stderr_lock, "\x1B[1A")
|
||||
}
|
||||
|
@ -270,7 +283,9 @@ fn clear_stdin(
|
|||
}
|
||||
|
||||
// Clear n-lines in terminal and move cursor to the beginning of the line.
|
||||
fn clear_n_lines(stderr_lock: &mut StderrLock, n: usize) {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn clear_n_lines(stderr_lock: &mut std::io::StderrLock, n: usize) {
|
||||
use std::io::Write;
|
||||
write!(stderr_lock, "\x1B[{n}A\x1B[0J").unwrap();
|
||||
}
|
||||
|
||||
|
@ -289,6 +304,11 @@ fn get_stdin_metadata() -> std::io::Result<std::fs::Metadata> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[derive(Default)]
|
||||
pub struct TtyPrompter;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl PermissionPrompter for TtyPrompter {
|
||||
fn prompt(
|
||||
&mut self,
|
||||
|
@ -298,6 +318,16 @@ impl PermissionPrompter for TtyPrompter {
|
|||
is_unary: bool,
|
||||
get_stack: Option<GetFormattedStackFn>,
|
||||
) -> PromptResponse {
|
||||
use std::fmt::Write;
|
||||
use std::io::BufRead;
|
||||
use std::io::IsTerminal;
|
||||
use std::io::Write as IoWrite;
|
||||
|
||||
use deno_terminal::colors;
|
||||
|
||||
// 10kB of permission prompting should be enough for anyone
|
||||
const MAX_PERMISSION_PROMPT_LENGTH: usize = 10 * 1024;
|
||||
|
||||
if !std::io::stdin().is_terminal() || !std::io::stderr().is_terminal() {
|
||||
return PromptResponse::Deny;
|
||||
};
|
||||
|
@ -381,7 +411,7 @@ impl PermissionPrompter for TtyPrompter {
|
|||
))
|
||||
);
|
||||
writeln!(&mut output, "┠─ {}", colors::italic(&msg)).unwrap();
|
||||
let msg = if is_standalone() {
|
||||
let msg = if crate::is_standalone() {
|
||||
format!("Specify the required permissions during compile time using `deno compile --allow-{name}`.")
|
||||
} else {
|
||||
format!("Run again with --allow-{name} to bypass this prompt.")
|
||||
|
|
186
runtime/permissions/which.rs
Normal file
186
runtime/permissions/which.rs
Normal file
|
@ -0,0 +1,186 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use temp_deno_which::sys::Sys;
|
||||
pub use temp_deno_which::Error;
|
||||
|
||||
pub fn which_in(
|
||||
sys: impl WhichSys,
|
||||
binary_name: &str,
|
||||
path: Option<OsString>,
|
||||
cwd: PathBuf,
|
||||
) -> Result<PathBuf, Error> {
|
||||
let sys = WhichSysAdapter(sys);
|
||||
let config = temp_deno_which::WhichConfig::new_with_sys(sys)
|
||||
.custom_cwd(cwd)
|
||||
.binary_name(OsString::from(binary_name));
|
||||
let config = match path {
|
||||
Some(path) => config.custom_path_list(path),
|
||||
None => config,
|
||||
};
|
||||
config.first_result()
|
||||
}
|
||||
|
||||
#[sys_traits::auto_impl]
|
||||
pub trait WhichSys:
|
||||
sys_traits::EnvHomeDir
|
||||
+ sys_traits::EnvCurrentDir
|
||||
+ sys_traits::EnvVar
|
||||
+ sys_traits::FsReadDir
|
||||
+ sys_traits::FsMetadata
|
||||
+ Clone
|
||||
+ 'static
|
||||
{
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WhichSysAdapter<TSys: WhichSys>(TSys);
|
||||
|
||||
impl<TSys: WhichSys> Sys for WhichSysAdapter<TSys> {
|
||||
type ReadDirEntry = WhichReadDirEntrySysAdapter<TSys::ReadDirEntry>;
|
||||
|
||||
type Metadata = WhichMetadataSysAdapter<TSys::Metadata>;
|
||||
|
||||
fn is_windows(&self) -> bool {
|
||||
sys_traits::impls::is_windows()
|
||||
}
|
||||
|
||||
fn current_dir(&self) -> std::io::Result<std::path::PathBuf> {
|
||||
self.0.env_current_dir()
|
||||
}
|
||||
|
||||
fn home_dir(&self) -> Option<std::path::PathBuf> {
|
||||
self.0.env_home_dir()
|
||||
}
|
||||
|
||||
fn env_split_paths(&self, paths: &OsStr) -> Vec<std::path::PathBuf> {
|
||||
if cfg!(target_arch = "wasm32") && self.is_windows() {
|
||||
// not perfect, but good enough
|
||||
paths
|
||||
.to_string_lossy()
|
||||
.split(";")
|
||||
.map(PathBuf::from)
|
||||
.collect()
|
||||
} else {
|
||||
std::env::split_paths(paths).collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn env_var_os(&self, name: &OsStr) -> Option<std::ffi::OsString> {
|
||||
self.0.env_var_os(name)
|
||||
}
|
||||
|
||||
fn metadata(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
) -> std::io::Result<Self::Metadata> {
|
||||
self.0.fs_metadata(path).map(WhichMetadataSysAdapter)
|
||||
}
|
||||
|
||||
fn symlink_metadata(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
) -> std::io::Result<Self::Metadata> {
|
||||
self
|
||||
.0
|
||||
.fs_symlink_metadata(path)
|
||||
.map(WhichMetadataSysAdapter)
|
||||
}
|
||||
|
||||
fn read_dir(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
) -> std::io::Result<
|
||||
Box<dyn Iterator<Item = std::io::Result<Self::ReadDirEntry>>>,
|
||||
> {
|
||||
let iter = self.0.fs_read_dir(path)?;
|
||||
let iter = Box::new(
|
||||
iter
|
||||
.into_iter()
|
||||
.map(|value| value.map(WhichReadDirEntrySysAdapter)),
|
||||
);
|
||||
Ok(iter)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn is_valid_executable(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
) -> std::io::Result<bool> {
|
||||
use nix::unistd::access;
|
||||
use nix::unistd::AccessFlags;
|
||||
|
||||
match access(path, AccessFlags::X_OK) {
|
||||
Ok(()) => Ok(true),
|
||||
Err(nix::errno::Errno::ENOENT) => Ok(false),
|
||||
Err(e) => Err(std::io::Error::from_raw_os_error(e as i32)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn is_valid_executable(
|
||||
&self,
|
||||
_path: &std::path::Path,
|
||||
) -> std::io::Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn is_valid_executable(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
) -> std::io::Result<bool> {
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
|
||||
let name = path
|
||||
.as_os_str()
|
||||
.encode_wide()
|
||||
.chain(Some(0))
|
||||
.collect::<Vec<u16>>();
|
||||
let mut bt: u32 = 0;
|
||||
// SAFETY: winapi call
|
||||
unsafe {
|
||||
Ok(
|
||||
windows_sys::Win32::Storage::FileSystem::GetBinaryTypeW(
|
||||
name.as_ptr(),
|
||||
&mut bt,
|
||||
) != 0,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WhichReadDirEntrySysAdapter<TFsDirEntry: sys_traits::FsDirEntry>(
|
||||
TFsDirEntry,
|
||||
);
|
||||
|
||||
impl<TFsDirEntry: sys_traits::FsDirEntry> temp_deno_which::sys::SysReadDirEntry
|
||||
for WhichReadDirEntrySysAdapter<TFsDirEntry>
|
||||
{
|
||||
fn file_name(&self) -> std::ffi::OsString {
|
||||
self.0.file_name().into_owned()
|
||||
}
|
||||
|
||||
fn path(&self) -> std::path::PathBuf {
|
||||
self.0.path().into_owned()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WhichMetadataSysAdapter<TMetadata: sys_traits::FsMetadataValue>(
|
||||
TMetadata,
|
||||
);
|
||||
|
||||
impl<TMetadata: sys_traits::FsMetadataValue> temp_deno_which::sys::SysMetadata
|
||||
for WhichMetadataSysAdapter<TMetadata>
|
||||
{
|
||||
fn is_symlink(&self) -> bool {
|
||||
self.0.file_type().is_symlink()
|
||||
}
|
||||
|
||||
fn is_file(&self) -> bool {
|
||||
self.0.file_type().is_file()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue