summaryrefslogtreecommitdiff
path: root/ext/fs/interface.rs
diff options
context:
space:
mode:
authorMatt Mastracci <matthew@mastracci.com>2024-04-19 18:12:03 -0600
committerGitHub <noreply@github.com>2024-04-19 18:12:03 -0600
commit472a37064071c66cd1311cdea2e78de8d2bc0641 (patch)
tree94459f249eee0429480e2cea6ac37319e27de41d /ext/fs/interface.rs
parent365e1f48f7059f94d4eeb8f5ba8b3949b686b355 (diff)
feat(runtime): Allow embedders to perform additional access checks on file open (#23208)
Embedders may have special requirements around file opening, so we add a new `check_open` permission check that is called as part of the file open process.
Diffstat (limited to 'ext/fs/interface.rs')
-rw-r--r--ext/fs/interface.rs67
1 files changed, 53 insertions, 14 deletions
diff --git a/ext/fs/interface.rs b/ext/fs/interface.rs
index c5a348eb1..70f9fdf63 100644
--- a/ext/fs/interface.rs
+++ b/ext/fs/interface.rs
@@ -80,6 +80,25 @@ pub struct FsDirEntry {
#[allow(clippy::disallowed_types)]
pub type FileSystemRc = crate::sync::MaybeArc<dyn FileSystem>;
+pub trait AccessCheckFn:
+ for<'a> FnMut(
+ bool,
+ &'a Path,
+ &'a OpenOptions,
+) -> FsResult<std::borrow::Cow<'a, Path>>
+{
+}
+impl<T> AccessCheckFn for T where
+ T: for<'a> FnMut(
+ bool,
+ &'a Path,
+ &'a OpenOptions,
+ ) -> FsResult<std::borrow::Cow<'a, Path>>
+{
+}
+
+pub type AccessCheckCb<'a> = &'a mut (dyn AccessCheckFn + 'a);
+
#[async_trait::async_trait(?Send)]
pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
fn cwd(&self) -> FsResult<PathBuf>;
@@ -91,11 +110,13 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
&self,
path: &Path,
options: OpenOptions,
+ access_check: Option<AccessCheckCb>,
) -> FsResult<Rc<dyn File>>;
- async fn open_async(
- &self,
+ async fn open_async<'a>(
+ &'a self,
path: PathBuf,
options: OpenOptions,
+ access_check: Option<AccessCheckCb<'a>>,
) -> FsResult<Rc<dyn File>>;
fn mkdir_sync(&self, path: &Path, recursive: bool, mode: u32)
@@ -202,22 +223,24 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
&self,
path: &Path,
options: OpenOptions,
+ access_check: Option<AccessCheckCb>,
data: &[u8],
) -> FsResult<()> {
- let file = self.open_sync(path, options)?;
+ let file = self.open_sync(path, options, access_check)?;
if let Some(mode) = options.mode {
file.clone().chmod_sync(mode)?;
}
file.write_all_sync(data)?;
Ok(())
}
- async fn write_file_async(
- &self,
+ async fn write_file_async<'a>(
+ &'a self,
path: PathBuf,
options: OpenOptions,
+ access_check: Option<AccessCheckCb<'a>>,
data: Vec<u8>,
) -> FsResult<()> {
- let file = self.open_async(path, options).await?;
+ let file = self.open_async(path, options, access_check).await?;
if let Some(mode) = options.mode {
file.clone().chmod_async(mode).await?;
}
@@ -225,15 +248,23 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
Ok(())
}
- fn read_file_sync(&self, path: &Path) -> FsResult<Vec<u8>> {
+ fn read_file_sync(
+ &self,
+ path: &Path,
+ access_check: Option<AccessCheckCb>,
+ ) -> FsResult<Vec<u8>> {
let options = OpenOptions::read();
- let file = self.open_sync(path, options)?;
+ let file = self.open_sync(path, options, access_check)?;
let buf = file.read_all_sync()?;
Ok(buf)
}
- async fn read_file_async(&self, path: PathBuf) -> FsResult<Vec<u8>> {
+ async fn read_file_async<'a>(
+ &'a self,
+ path: PathBuf,
+ access_check: Option<AccessCheckCb<'a>>,
+ ) -> FsResult<Vec<u8>> {
let options = OpenOptions::read();
- let file = self.open_async(path, options).await?;
+ let file = self.open_async(path, options, access_check).await?;
let buf = file.read_all_async().await?;
Ok(buf)
}
@@ -253,14 +284,22 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
self.stat_sync(path).is_ok()
}
- fn read_text_file_sync(&self, path: &Path) -> FsResult<String> {
- let buf = self.read_file_sync(path)?;
+ fn read_text_file_sync(
+ &self,
+ path: &Path,
+ access_check: Option<AccessCheckCb>,
+ ) -> FsResult<String> {
+ let buf = self.read_file_sync(path, access_check)?;
String::from_utf8(buf).map_err(|err| {
std::io::Error::new(std::io::ErrorKind::InvalidData, err).into()
})
}
- async fn read_text_file_async(&self, path: PathBuf) -> FsResult<String> {
- let buf = self.read_file_async(path).await?;
+ async fn read_text_file_async<'a>(
+ &'a self,
+ path: PathBuf,
+ access_check: Option<AccessCheckCb<'a>>,
+ ) -> FsResult<String> {
+ let buf = self.read_file_async(path, access_check).await?;
String::from_utf8(buf).map_err(|err| {
std::io::Error::new(std::io::ErrorKind::InvalidData, err).into()
})