|
|
@ -5,7 +5,7 @@ use std::path::{
|
|
|
|
Path,
|
|
|
|
Path,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
|
fs, io,
|
|
|
|
fs, io, ops,
|
|
|
|
borrow::{
|
|
|
|
borrow::{
|
|
|
|
Cow, Borrow,
|
|
|
|
Cow, Borrow,
|
|
|
|
},
|
|
|
|
},
|
|
|
@ -561,6 +561,32 @@ impl<P: AsRef<Path>> LookupVisitor<P>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, T: ToOwned<Owned = PathBuf> + 'a> From<(T, bool)> for PluginTrust<'a>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fn from((from, trust): (T, bool)) -> Self
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(if trust {
|
|
|
|
|
|
|
|
Self::Trusted
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
Self::Untrusted
|
|
|
|
|
|
|
|
})(Cow::Owned(from.to_owned()))
|
|
|
|
|
|
|
|
.enforce_validity::<true>()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a> From<locations::PathTrust<'a>> for PluginTrust<'a>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
|
|
|
fn from(from: locations::PathTrust<'a>) -> Self
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
match from {
|
|
|
|
|
|
|
|
locations::PathTrust::Trusted(a) => PluginTrust::Trusted(Cow::from(Path::new(a))),
|
|
|
|
|
|
|
|
locations::PathTrust::Untrusted(a) => PluginTrust::Untrusted(Cow::from(Path::new(a))),
|
|
|
|
|
|
|
|
}.enforce_validity::<true>()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Denoted a plugin and if it was loaded from a trusted path or not
|
|
|
|
/// Denoted a plugin and if it was loaded from a trusted path or not
|
|
|
|
#[derive(Debug, Clone, Eq, Hash, PartialOrd, Ord)]
|
|
|
|
#[derive(Debug, Clone, Eq, Hash, PartialOrd, Ord)]
|
|
|
|
pub enum PluginTrust<'a>
|
|
|
|
pub enum PluginTrust<'a>
|
|
|
@ -569,6 +595,15 @@ pub enum PluginTrust<'a>
|
|
|
|
Untrusted(Cow<'a, Path>)
|
|
|
|
Untrusted(Cow<'a, Path>)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a> ops::Deref for PluginTrust<'a>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
type Target = Path;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
|
|
|
|
self.as_path()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a> Borrow<Path> for PluginTrust<'a>
|
|
|
|
impl<'a> Borrow<Path> for PluginTrust<'a>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#[inline(always)]
|
|
|
|
#[inline(always)]
|
|
|
@ -600,6 +635,15 @@ impl<'a> From<PluginTrust<'a>> for Cow<'a, Path>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a> From<PluginTrust<'a>> for PathBuf
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
|
|
|
fn from(from: PluginTrust<'a>) -> Self {
|
|
|
|
|
|
|
|
let cow: Cow<Path> = from.into();
|
|
|
|
|
|
|
|
cow.into_owned()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, T: AsRef<Path> + ?Sized> PartialEq<T> for PluginTrust<'a>
|
|
|
|
impl<'a, T: AsRef<Path> + ?Sized> PartialEq<T> for PluginTrust<'a>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#[inline]
|
|
|
|
#[inline]
|
|
|
@ -628,15 +672,52 @@ impl<'a> PluginTrust<'a>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
!self.is_trusted()
|
|
|
|
!self.is_trusted()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl From<PluginTrust<'static>> for PathBuf
|
|
|
|
/// Get the `Path`, trusted or otherwise.
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn as_path(&self) -> &Path
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
self.borrow()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Map this path to another.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// # Panics
|
|
|
|
|
|
|
|
/// If the output of `func` is not a file-like object or does not exist.
|
|
|
|
#[inline]
|
|
|
|
#[inline]
|
|
|
|
fn from(from: PluginTrust<'static>) -> Self
|
|
|
|
pub fn map<F, T: Into<Cow<'a, Path>>>(self, func: F) -> Self
|
|
|
|
|
|
|
|
where F: FnOnce(Cow<'a, Path>) -> T
|
|
|
|
{
|
|
|
|
{
|
|
|
|
match from {
|
|
|
|
match self {
|
|
|
|
PluginTrust::Trusted(a) | PluginTrust::Untrusted(a) => a.into_owned()
|
|
|
|
Self::Trusted(yes) => Self::Trusted(func(yes).into()),
|
|
|
|
|
|
|
|
Self::Untrusted(no) => Self::Untrusted(func(no).into())
|
|
|
|
|
|
|
|
}.enforce_validity::<false>()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
pub(super) fn is_valid(&self) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let path = self.as_path();
|
|
|
|
|
|
|
|
path.exists() && !path.is_dir() //XXX: Is this okay for validation for now? What about symlinked files?
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn enforce_validity<const DEBUG: bool>(self) -> Self
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if !DEBUG || cfg!(debug_assertions) {
|
|
|
|
|
|
|
|
#[inline(never)]
|
|
|
|
|
|
|
|
#[cold]
|
|
|
|
|
|
|
|
fn _panic_invalid(path: impl Into<PathBuf>) -> !
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
panic!("Illegal plugin path name: {:?}", path.into())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if !self.is_valid() {
|
|
|
|
|
|
|
|
_panic_invalid(self)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
self
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|