summaryrefslogtreecommitdiff
path: root/ext/fs/ops.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-09-16 21:39:37 +0100
committerGitHub <noreply@github.com>2024-09-16 21:39:37 +0100
commit62e952559f600e72d7498c9b12f906cb0b1ba150 (patch)
tree6dbcce6592973358ef4bf6341888b0bbbdb98cc5 /ext/fs/ops.rs
parente0b9c745c15720914f14996bf357d5b375e2dbd8 (diff)
refactor(permissions): split up Descriptor into Allow, Deny, and Query (#25508)
This makes the permission system more versatile.
Diffstat (limited to 'ext/fs/ops.rs')
-rw-r--r--ext/fs/ops.rs302
1 files changed, 144 insertions, 158 deletions
diff --git a/ext/fs/ops.rs b/ext/fs/ops.rs
index f25cd944d..150d3b955 100644
--- a/ext/fs/ops.rs
+++ b/ext/fs/ops.rs
@@ -5,6 +5,7 @@ use std::io;
use std::io::SeekFrom;
use std::path::Path;
use std::path::PathBuf;
+use std::path::StripPrefixError;
use std::rc::Rc;
use deno_core::anyhow::bail;
@@ -105,8 +106,9 @@ pub fn op_fs_chdir<P>(
where
P: FsPermissions + 'static,
{
- let d = PathBuf::from(&directory);
- state.borrow_mut::<P>().check_read(&d, "Deno.chdir()")?;
+ let d = state
+ .borrow_mut::<P>()
+ .check_read(directory, "Deno.chdir()")?;
state
.borrow::<FileSystemRc>()
.chdir(&d)
@@ -188,11 +190,9 @@ pub fn op_fs_mkdir_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
let mode = mode.unwrap_or(0o777) & 0o777;
- state
+ let path = state
.borrow_mut::<P>()
.check_write(&path, "Deno.mkdirSync()")?;
@@ -213,14 +213,12 @@ pub async fn op_fs_mkdir_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
let mode = mode.unwrap_or(0o777) & 0o777;
- let fs = {
+ let (fs, path) = {
let mut state = state.borrow_mut();
- state.borrow_mut::<P>().check_write(&path, "Deno.mkdir()")?;
- state.borrow::<FileSystemRc>().clone()
+ let path = state.borrow_mut::<P>().check_write(&path, "Deno.mkdir()")?;
+ (state.borrow::<FileSystemRc>().clone(), path)
};
fs.mkdir_async(path.clone(), recursive, mode)
@@ -239,8 +237,7 @@ pub fn op_fs_chmod_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
- state
+ let path = state
.borrow_mut::<P>()
.check_write(&path, "Deno.chmodSync()")?;
let fs = state.borrow::<FileSystemRc>();
@@ -257,11 +254,10 @@ pub async fn op_fs_chmod_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
- let fs = {
+ let (fs, path) = {
let mut state = state.borrow_mut();
- state.borrow_mut::<P>().check_write(&path, "Deno.chmod()")?;
- state.borrow::<FileSystemRc>().clone()
+ let path = state.borrow_mut::<P>().check_write(&path, "Deno.chmod()")?;
+ (state.borrow::<FileSystemRc>().clone(), path)
};
fs.chmod_async(path.clone(), mode)
.await
@@ -279,8 +275,7 @@ pub fn op_fs_chown_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
- state
+ let path = state
.borrow_mut::<P>()
.check_write(&path, "Deno.chownSync()")?;
let fs = state.borrow::<FileSystemRc>();
@@ -299,11 +294,10 @@ pub async fn op_fs_chown_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
- let fs = {
+ let (fs, path) = {
let mut state = state.borrow_mut();
- state.borrow_mut::<P>().check_write(&path, "Deno.chown()")?;
- state.borrow::<FileSystemRc>().clone()
+ let path = state.borrow_mut::<P>().check_write(&path, "Deno.chown()")?;
+ (state.borrow::<FileSystemRc>().clone(), path)
};
fs.chown_async(path.clone(), uid, gid)
.await
@@ -320,11 +314,9 @@ pub fn op_fs_remove_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- state
+ let path = state
.borrow_mut::<P>()
- .check_write(&path, "Deno.removeSync()")?;
+ .check_write(path, "Deno.removeSync()")?;
let fs = state.borrow::<FileSystemRc>();
fs.remove_sync(&path, recursive)
@@ -342,21 +334,19 @@ pub async fn op_fs_remove_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- let fs = {
+ let (fs, path) = {
let mut state = state.borrow_mut();
- if recursive {
+ let path = if recursive {
state
.borrow_mut::<P>()
- .check_write(&path, "Deno.remove()")?;
+ .check_write(&path, "Deno.remove()")?
} else {
state
.borrow_mut::<P>()
- .check_write_partial(&path, "Deno.remove()")?;
- }
+ .check_write_partial(&path, "Deno.remove()")?
+ };
- state.borrow::<FileSystemRc>().clone()
+ (state.borrow::<FileSystemRc>().clone(), path)
};
fs.remove_async(path.clone(), recursive)
@@ -375,12 +365,9 @@ pub fn op_fs_copy_file_sync<P>(
where
P: FsPermissions + 'static,
{
- let from = PathBuf::from(from);
- let to = PathBuf::from(to);
-
let permissions = state.borrow_mut::<P>();
- permissions.check_read(&from, "Deno.copyFileSync()")?;
- permissions.check_write(&to, "Deno.copyFileSync()")?;
+ let from = permissions.check_read(from, "Deno.copyFileSync()")?;
+ let to = permissions.check_write(to, "Deno.copyFileSync()")?;
let fs = state.borrow::<FileSystemRc>();
fs.copy_file_sync(&from, &to)
@@ -398,15 +385,12 @@ pub async fn op_fs_copy_file_async<P>(
where
P: FsPermissions + 'static,
{
- let from = PathBuf::from(from);
- let to = PathBuf::from(to);
-
- let fs = {
+ let (fs, from, to) = {
let mut state = state.borrow_mut();
let permissions = state.borrow_mut::<P>();
- permissions.check_read(&from, "Deno.copyFile()")?;
- permissions.check_write(&to, "Deno.copyFile()")?;
- state.borrow::<FileSystemRc>().clone()
+ let from = permissions.check_read(&from, "Deno.copyFile()")?;
+ let to = permissions.check_write(&to, "Deno.copyFile()")?;
+ (state.borrow::<FileSystemRc>().clone(), from, to)
};
fs.copy_file_async(from.clone(), to.clone())
@@ -425,8 +409,7 @@ pub fn op_fs_stat_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
- state
+ let path = state
.borrow_mut::<P>()
.check_read(&path, "Deno.statSync()")?;
let fs = state.borrow::<FileSystemRc>();
@@ -445,12 +428,11 @@ pub async fn op_fs_stat_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
- let fs = {
+ let (fs, path) = {
let mut state = state.borrow_mut();
let permissions = state.borrow_mut::<P>();
- permissions.check_read(&path, "Deno.stat()")?;
- state.borrow::<FileSystemRc>().clone()
+ let path = permissions.check_read(&path, "Deno.stat()")?;
+ (state.borrow::<FileSystemRc>().clone(), path)
};
let stat = fs
.stat_async(path.clone())
@@ -468,8 +450,7 @@ pub fn op_fs_lstat_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
- state
+ let path = state
.borrow_mut::<P>()
.check_read(&path, "Deno.lstatSync()")?;
let fs = state.borrow::<FileSystemRc>();
@@ -488,12 +469,11 @@ pub async fn op_fs_lstat_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
- let fs = {
+ let (fs, path) = {
let mut state = state.borrow_mut();
let permissions = state.borrow_mut::<P>();
- permissions.check_read(&path, "Deno.lstat()")?;
- state.borrow::<FileSystemRc>().clone()
+ let path = permissions.check_read(&path, "Deno.lstat()")?;
+ (state.borrow::<FileSystemRc>().clone(), path)
};
let stat = fs
.lstat_async(path.clone())
@@ -511,11 +491,9 @@ pub fn op_fs_realpath_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
let fs = state.borrow::<FileSystemRc>().clone();
let permissions = state.borrow_mut::<P>();
- permissions.check_read(&path, "Deno.realPathSync()")?;
+ let path = permissions.check_read(&path, "Deno.realPathSync()")?;
if path.is_relative() {
permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPathSync()")?;
}
@@ -536,18 +514,16 @@ pub async fn op_fs_realpath_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- let fs;
- {
+ let (fs, path) = {
let mut state = state.borrow_mut();
- fs = state.borrow::<FileSystemRc>().clone();
+ let fs = state.borrow::<FileSystemRc>().clone();
let permissions = state.borrow_mut::<P>();
- permissions.check_read(&path, "Deno.realPath()")?;
+ let path = permissions.check_read(&path, "Deno.realPath()")?;
if path.is_relative() {
permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPath()")?;
}
- }
+ (fs, path)
+ };
let resolved_path = fs
.realpath_async(path.clone())
.await
@@ -566,9 +542,7 @@ pub fn op_fs_read_dir_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- state
+ let path = state
.borrow_mut::<P>()
.check_read(&path, "Deno.readDirSync()")?;
@@ -587,14 +561,12 @@ pub async fn op_fs_read_dir_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- let fs = {
+ let (fs, path) = {
let mut state = state.borrow_mut();
- state
+ let path = state
.borrow_mut::<P>()
.check_read(&path, "Deno.readDir()")?;
- state.borrow::<FileSystemRc>().clone()
+ (state.borrow::<FileSystemRc>().clone(), path)
};
let entries = fs
@@ -614,13 +586,10 @@ pub fn op_fs_rename_sync<P>(
where
P: FsPermissions + 'static,
{
- let oldpath = PathBuf::from(oldpath);
- let newpath = PathBuf::from(newpath);
-
let permissions = state.borrow_mut::<P>();
- permissions.check_read(&oldpath, "Deno.renameSync()")?;
- permissions.check_write(&oldpath, "Deno.renameSync()")?;
- permissions.check_write(&newpath, "Deno.renameSync()")?;
+ let _ = permissions.check_read(&oldpath, "Deno.renameSync()")?;
+ let oldpath = permissions.check_write(&oldpath, "Deno.renameSync()")?;
+ let newpath = permissions.check_write(&newpath, "Deno.renameSync()")?;
let fs = state.borrow::<FileSystemRc>();
fs.rename_sync(&oldpath, &newpath)
@@ -638,16 +607,13 @@ pub async fn op_fs_rename_async<P>(
where
P: FsPermissions + 'static,
{
- let oldpath = PathBuf::from(oldpath);
- let newpath = PathBuf::from(newpath);
-
- let fs = {
+ let (fs, oldpath, newpath) = {
let mut state = state.borrow_mut();
let permissions = state.borrow_mut::<P>();
- permissions.check_read(&oldpath, "Deno.rename()")?;
- permissions.check_write(&oldpath, "Deno.rename()")?;
- permissions.check_write(&newpath, "Deno.rename()")?;
- state.borrow::<FileSystemRc>().clone()
+ _ = permissions.check_read(&oldpath, "Deno.rename()")?;
+ let oldpath = permissions.check_write(&oldpath, "Deno.rename()")?;
+ let newpath = permissions.check_write(&newpath, "Deno.rename()")?;
+ (state.borrow::<FileSystemRc>().clone(), oldpath, newpath)
};
fs.rename_async(oldpath.clone(), newpath.clone())
@@ -666,14 +632,11 @@ pub fn op_fs_link_sync<P>(
where
P: FsPermissions + 'static,
{
- let oldpath = PathBuf::from(oldpath);
- let newpath = PathBuf::from(newpath);
-
let permissions = state.borrow_mut::<P>();
- permissions.check_read(&oldpath, "Deno.linkSync()")?;
- permissions.check_write(&oldpath, "Deno.linkSync()")?;
- permissions.check_read(&newpath, "Deno.linkSync()")?;
- permissions.check_write(&newpath, "Deno.linkSync()")?;
+ _ = permissions.check_read(oldpath, "Deno.linkSync()")?;
+ let oldpath = permissions.check_write(oldpath, "Deno.linkSync()")?;
+ _ = permissions.check_read(newpath, "Deno.linkSync()")?;
+ let newpath = permissions.check_write(newpath, "Deno.linkSync()")?;
let fs = state.borrow::<FileSystemRc>();
fs.link_sync(&oldpath, &newpath)
@@ -691,17 +654,14 @@ pub async fn op_fs_link_async<P>(
where
P: FsPermissions + 'static,
{
- let oldpath = PathBuf::from(&oldpath);
- let newpath = PathBuf::from(&newpath);
-
- let fs = {
+ let (fs, oldpath, newpath) = {
let mut state = state.borrow_mut();
let permissions = state.borrow_mut::<P>();
- permissions.check_read(&oldpath, "Deno.link()")?;
- permissions.check_write(&oldpath, "Deno.link()")?;
- permissions.check_read(&newpath, "Deno.link()")?;
- permissions.check_write(&newpath, "Deno.link()")?;
- state.borrow::<FileSystemRc>().clone()
+ _ = permissions.check_read(&oldpath, "Deno.link()")?;
+ let oldpath = permissions.check_write(&oldpath, "Deno.link()")?;
+ _ = permissions.check_read(&newpath, "Deno.link()")?;
+ let newpath = permissions.check_write(&newpath, "Deno.link()")?;
+ (state.borrow::<FileSystemRc>().clone(), oldpath, newpath)
};
fs.link_async(oldpath.clone(), newpath.clone())
@@ -772,9 +732,7 @@ pub fn op_fs_read_link_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- state
+ let path = state
.borrow_mut::<P>()
.check_read(&path, "Deno.readLink()")?;
@@ -794,14 +752,12 @@ pub async fn op_fs_read_link_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- let fs = {
+ let (fs, path) = {
let mut state = state.borrow_mut();
- state
+ let path = state
.borrow_mut::<P>()
.check_read(&path, "Deno.readLink()")?;
- state.borrow::<FileSystemRc>().clone()
+ (state.borrow::<FileSystemRc>().clone(), path)
};
let target = fs
@@ -821,11 +777,9 @@ pub fn op_fs_truncate_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- state
+ let path = state
.borrow_mut::<P>()
- .check_write(&path, "Deno.truncateSync()")?;
+ .check_write(path, "Deno.truncateSync()")?;
let fs = state.borrow::<FileSystemRc>();
fs.truncate_sync(&path, len)
@@ -843,14 +797,12 @@ pub async fn op_fs_truncate_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- let fs = {
+ let (fs, path) = {
let mut state = state.borrow_mut();
- state
+ let path = state
.borrow_mut::<P>()
.check_write(&path, "Deno.truncate()")?;
- state.borrow::<FileSystemRc>().clone()
+ (state.borrow::<FileSystemRc>().clone(), path)
};
fs.truncate_async(path.clone(), len)
@@ -872,9 +824,7 @@ pub fn op_fs_utime_sync<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- state.borrow_mut::<P>().check_write(&path, "Deno.utime()")?;
+ let path = state.borrow_mut::<P>().check_write(path, "Deno.utime()")?;
let fs = state.borrow::<FileSystemRc>();
fs.utime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
@@ -895,12 +845,10 @@ pub async fn op_fs_utime_async<P>(
where
P: FsPermissions + 'static,
{
- let path = PathBuf::from(path);
-
- let fs = {
+ let (fs, path) = {
let mut state = state.borrow_mut();
- state.borrow_mut::<P>().check_write(&path, "Deno.utime()")?;
- state.borrow::<FileSystemRc>().clone()
+ let path = state.borrow_mut::<P>().check_write(&path, "Deno.utime()")?;
+ (state.borrow::<FileSystemRc>().clone(), path)
};
fs.utime_async(
@@ -920,15 +868,18 @@ where
#[string]
pub fn op_fs_make_temp_dir_sync<P>(
state: &mut OpState,
- #[string] dir: Option<String>,
+ #[string] dir_arg: Option<String>,
#[string] prefix: Option<String>,
#[string] suffix: Option<String>,
) -> Result<String, AnyError>
where
P: FsPermissions + 'static,
{
- let (dir, fs) =
- make_temp_check_sync::<P>(state, dir, "Deno.makeTempDirSync()")?;
+ let (dir, fs) = make_temp_check_sync::<P>(
+ state,
+ dir_arg.as_deref(),
+ "Deno.makeTempDirSync()",
+ )?;
let mut rng = thread_rng();
@@ -936,7 +887,11 @@ where
for _ in 0..MAX_TRIES {
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
match fs.mkdir_sync(&path, false, 0o700) {
- Ok(_) => return path_into_string(path.into_os_string()),
+ Ok(_) => {
+ // PERMISSIONS: ensure the absolute path is not leaked
+ let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?;
+ return path_into_string(path.into_os_string());
+ }
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
continue;
}
@@ -955,14 +910,18 @@ where
#[string]
pub async fn op_fs_make_temp_dir_async<P>(
state: Rc<RefCell<OpState>>,
- #[string] dir: Option<String>,
+ #[string] dir_arg: Option<String>,
#[string] prefix: Option<String>,
#[string] suffix: Option<String>,
) -> Result<String, AnyError>
where
P: FsPermissions + 'static,
{
- let (dir, fs) = make_temp_check_async::<P>(state, dir, "Deno.makeTempDir()")?;
+ let (dir, fs) = make_temp_check_async::<P>(
+ state,
+ dir_arg.as_deref(),
+ "Deno.makeTempDir()",
+ )?;
let mut rng = thread_rng();
@@ -970,7 +929,11 @@ where
for _ in 0..MAX_TRIES {
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
match fs.clone().mkdir_async(path.clone(), false, 0o700).await {
- Ok(_) => return path_into_string(path.into_os_string()),
+ Ok(_) => {
+ // PERMISSIONS: ensure the absolute path is not leaked
+ let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?;
+ return path_into_string(path.into_os_string());
+ }
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
continue;
}
@@ -989,15 +952,18 @@ where
#[string]
pub fn op_fs_make_temp_file_sync<P>(
state: &mut OpState,
- #[string] dir: Option<String>,
+ #[string] dir_arg: Option<String>,
#[string] prefix: Option<String>,
#[string] suffix: Option<String>,
) -> Result<String, AnyError>
where
P: FsPermissions + 'static,
{
- let (dir, fs) =
- make_temp_check_sync::<P>(state, dir, "Deno.makeTempFileSync()")?;
+ let (dir, fs) = make_temp_check_sync::<P>(
+ state,
+ dir_arg.as_deref(),
+ "Deno.makeTempFileSync()",
+ )?;
let open_opts = OpenOptions {
write: true,
@@ -1011,7 +977,11 @@ where
for _ in 0..MAX_TRIES {
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
match fs.open_sync(&path, open_opts, None) {
- Ok(_) => return path_into_string(path.into_os_string()),
+ Ok(_) => {
+ // PERMISSIONS: ensure the absolute path is not leaked
+ let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?;
+ return path_into_string(path.into_os_string());
+ }
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
continue;
}
@@ -1030,15 +1000,18 @@ where
#[string]
pub async fn op_fs_make_temp_file_async<P>(
state: Rc<RefCell<OpState>>,
- #[string] dir: Option<String>,
+ #[string] dir_arg: Option<String>,
#[string] prefix: Option<String>,
#[string] suffix: Option<String>,
) -> Result<String, AnyError>
where
P: FsPermissions + 'static,
{
- let (dir, fs) =
- make_temp_check_async::<P>(state, dir, "Deno.makeTempFile()")?;
+ let (dir, fs) = make_temp_check_async::<P>(
+ state,
+ dir_arg.as_deref(),
+ "Deno.makeTempFile()",
+ )?;
let open_opts = OpenOptions {
write: true,
@@ -1053,7 +1026,11 @@ where
for _ in 0..MAX_TRIES {
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
match fs.clone().open_async(path.clone(), open_opts, None).await {
- Ok(_) => return path_into_string(path.into_os_string()),
+ Ok(_) => {
+ // PERMISSIONS: ensure the absolute path is not leaked
+ let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?;
+ return path_into_string(path.into_os_string());
+ }
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
continue;
}
@@ -1067,9 +1044,26 @@ where
.context("tmpfile")
}
+fn strip_dir_prefix(
+ resolved_dir: &Path,
+ dir_arg: Option<&str>,
+ result_path: PathBuf,
+) -> Result<PathBuf, StripPrefixError> {
+ if resolved_dir.is_absolute() {
+ match &dir_arg {
+ Some(dir_arg) => {
+ Ok(Path::new(dir_arg).join(result_path.strip_prefix(resolved_dir)?))
+ }
+ None => Ok(result_path),
+ }
+ } else {
+ Ok(result_path)
+ }
+}
+
fn make_temp_check_sync<P>(
state: &mut OpState,
- dir: Option<String>,
+ dir: Option<&str>,
api_name: &str,
) -> Result<(PathBuf, FileSystemRc), AnyError>
where
@@ -1077,11 +1071,7 @@ where
{
let fs = state.borrow::<FileSystemRc>().clone();
let dir = match dir {
- Some(dir) => {
- let dir = PathBuf::from(dir);
- state.borrow_mut::<P>().check_write(&dir, api_name)?;
- dir
- }
+ Some(dir) => state.borrow_mut::<P>().check_write(dir, api_name)?,
None => {
let dir = fs.tmp_dir().context("tmpdir")?;
state
@@ -1095,7 +1085,7 @@ where
fn make_temp_check_async<P>(
state: Rc<RefCell<OpState>>,
- dir: Option<String>,
+ dir: Option<&str>,
api_name: &str,
) -> Result<(PathBuf, FileSystemRc), AnyError>
where
@@ -1104,11 +1094,7 @@ where
let mut state = state.borrow_mut();
let fs = state.borrow::<FileSystemRc>().clone();
let dir = match dir {
- Some(dir) => {
- let dir = PathBuf::from(dir);
- state.borrow_mut::<P>().check_write(&dir, api_name)?;
- dir
- }
+ Some(dir) => state.borrow_mut::<P>().check_write(dir, api_name)?,
None => {
let dir = fs.tmp_dir().context("tmpdir")?;
state