Skip to content

Commit 92d91b5

Browse files
authored
fix: allow call sync file apis in /s3 prefix (#556)
* chore: add an integration test * fix: allow call sync apis in s3 prefix * stamp: makes clippy happy
1 parent ce80bf9 commit 92d91b5

File tree

8 files changed

+587
-250
lines changed

8 files changed

+587
-250
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/base/src/runtime/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -651,15 +651,22 @@ where
651651
let tmp_fs =
652652
TmpFs::try_from(maybe_tmp_fs_config.unwrap_or_default())?;
653653
let tmp_fs_actual_path = tmp_fs.actual_path().to_path_buf();
654-
let fs = PrefixFs::new("/tmp", tmp_fs.clone(), Some(base_fs))
654+
let mut fs = PrefixFs::new("/tmp", tmp_fs.clone(), Some(base_fs))
655655
.tmp_dir("/tmp")
656656
.add_fs(tmp_fs_actual_path, tmp_fs);
657657

658+
fs
659+
.set_runtime_state(&runtime_state);
660+
658661
Ok(
659662
if let Some(s3_fs) =
660663
maybe_s3_fs_config.map(S3Fs::new).transpose()?
661664
{
662-
(Arc::new(fs.add_fs("/s3", s3_fs.clone())), Some(s3_fs))
665+
let mut s3_prefix_fs = fs.add_fs("/s3", s3_fs.clone());
666+
667+
s3_prefix_fs.set_check_sync_api(is_user_worker);
668+
669+
(Arc::new(s3_prefix_fs), Some(s3_fs))
663670
} else {
664671
(Arc::new(fs), None)
665672
},

crates/fs/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ deno_semver.workspace = true
2020

2121
eszip_trait.workspace = true
2222

23+
base_rt.workspace = true
2324
ext_node.workspace = true
2425

2526
anyhow.workspace = true

crates/fs/impl/prefix_fs.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use std::path::PathBuf;
55
use std::rc::Rc;
66
use std::sync::Arc;
77

8+
use anyhow::anyhow;
9+
use base_rt::RuntimeState;
810
use deno_fs::AccessCheckCb;
911
use deno_fs::FsDirEntry;
1012
use deno_fs::FsFileType;
@@ -21,6 +23,8 @@ pub struct PrefixFs<FileSystem> {
2123
tmp_dir: Option<PathBuf>,
2224
fs: Arc<FileSystem>,
2325
base_fs: Option<Arc<dyn deno_fs::FileSystem>>,
26+
runtime_state: Option<Arc<RuntimeState>>,
27+
check_sync_api: bool,
2428
}
2529

2630
impl<FileSystem> PrefixFs<FileSystem>
@@ -41,6 +45,8 @@ where
4145
tmp_dir: None,
4246
fs: Arc::new(fs),
4347
base_fs,
48+
runtime_state: None,
49+
check_sync_api: false,
4450
}
4551
}
4652

@@ -75,6 +81,16 @@ where
7581
self.tmp_dir = Some(v.as_ref().to_path_buf());
7682
self
7783
}
84+
85+
pub fn set_runtime_state(&mut self, v: &Arc<RuntimeState>) -> &mut Self {
86+
self.runtime_state = Some(v.clone());
87+
self
88+
}
89+
90+
pub fn set_check_sync_api(&mut self, v: bool) -> &mut Self {
91+
self.check_sync_api = v;
92+
self
93+
}
7894
}
7995

8096
impl<FileSystem> PrefixFs<FileSystem>
@@ -95,6 +111,8 @@ where
95111
fs: Arc::new(fs),
96112
cwd: self.cwd.take(),
97113
tmp_dir: self.tmp_dir.take(),
114+
runtime_state: self.runtime_state.clone(),
115+
check_sync_api: self.check_sync_api,
98116
base_fs: Some(Arc::new(self)),
99117
}
100118
}
@@ -149,6 +167,7 @@ where
149167
options: OpenOptions,
150168
access_check: Option<AccessCheckCb>,
151169
) -> FsResult<Rc<dyn File>> {
170+
self.check_sync_api_allowed("open_sync")?;
152171
if path.starts_with(&self.prefix) {
153172
self.fs.open_sync(
154173
path.strip_prefix(&self.prefix).unwrap(),
@@ -194,6 +213,7 @@ where
194213
recursive: bool,
195214
mode: Option<u32>,
196215
) -> FsResult<()> {
216+
self.check_sync_api_allowed("mkdir_sync")?;
197217
if path.starts_with(&self.prefix) {
198218
self.fs.mkdir_sync(
199219
path.strip_prefix(&self.prefix).unwrap(),
@@ -232,6 +252,7 @@ where
232252
}
233253

234254
fn chmod_sync(&self, path: &Path, mode: u32) -> FsResult<()> {
255+
self.check_sync_api_allowed("chmod_sync")?;
235256
if path.starts_with(&self.prefix) {
236257
self
237258
.fs
@@ -264,6 +285,7 @@ where
264285
uid: Option<u32>,
265286
gid: Option<u32>,
266287
) -> FsResult<()> {
288+
self.check_sync_api_allowed("chown_sync")?;
267289
if path.starts_with(&self.prefix) {
268290
self
269291
.fs
@@ -305,6 +327,7 @@ where
305327
uid: Option<u32>,
306328
gid: Option<u32>,
307329
) -> FsResult<()> {
330+
self.check_sync_api_allowed("lchown_sync")?;
308331
if path.starts_with(&self.prefix) {
309332
self
310333
.fs
@@ -341,6 +364,7 @@ where
341364
}
342365

343366
fn remove_sync(&self, path: &Path, recursive: bool) -> FsResult<()> {
367+
self.check_sync_api_allowed("remove_sync")?;
344368
if path.starts_with(&self.prefix) {
345369
self
346370
.fs
@@ -371,6 +395,8 @@ where
371395
}
372396

373397
fn copy_file_sync(&self, oldpath: &Path, newpath: &Path) -> FsResult<()> {
398+
self.check_sync_api_allowed("copy_file_sync")?;
399+
374400
let oldpath_matches = oldpath.starts_with(&self.prefix);
375401
let newpath_matches = newpath.starts_with(&self.prefix);
376402
if oldpath_matches || newpath_matches {
@@ -426,6 +452,8 @@ where
426452
}
427453

428454
fn cp_sync(&self, path: &Path, new_path: &Path) -> FsResult<()> {
455+
self.check_sync_api_allowed("cp_sync")?;
456+
429457
let path_matches = path.starts_with(&self.prefix);
430458
let new_path_matches = new_path.starts_with(&self.prefix);
431459
if path_matches || new_path_matches {
@@ -477,6 +505,7 @@ where
477505
}
478506

479507
fn stat_sync(&self, path: &Path) -> FsResult<FsStat> {
508+
self.check_sync_api_allowed("stat_sync")?;
480509
if path.starts_with(&self.prefix) {
481510
self.fs.stat_sync(path.strip_prefix(&self.prefix).unwrap())
482511
} else {
@@ -502,6 +531,7 @@ where
502531
}
503532

504533
fn lstat_sync(&self, path: &Path) -> FsResult<FsStat> {
534+
self.check_sync_api_allowed("lstat_sync")?;
505535
if path.starts_with(&self.prefix) {
506536
self.fs.lstat_sync(path.strip_prefix(&self.prefix).unwrap())
507537
} else {
@@ -527,6 +557,7 @@ where
527557
}
528558

529559
fn realpath_sync(&self, path: &Path) -> FsResult<PathBuf> {
560+
self.check_sync_api_allowed("realpath_sync")?;
530561
if path.starts_with(&self.prefix) {
531562
self
532563
.fs
@@ -554,6 +585,7 @@ where
554585
}
555586

556587
fn read_dir_sync(&self, path: &Path) -> FsResult<Vec<FsDirEntry>> {
588+
self.check_sync_api_allowed("read_dir_sync")?;
557589
if path.starts_with(&self.prefix) {
558590
self
559591
.fs
@@ -581,6 +613,8 @@ where
581613
}
582614

583615
fn rename_sync(&self, oldpath: &Path, newpath: &Path) -> FsResult<()> {
616+
self.check_sync_api_allowed("rename_sync")?;
617+
584618
let oldpath_matches = oldpath.starts_with(&self.prefix);
585619
let newpath_matches = newpath.starts_with(&self.prefix);
586620
if oldpath_matches || newpath_matches {
@@ -636,6 +670,8 @@ where
636670
}
637671

638672
fn link_sync(&self, oldpath: &Path, newpath: &Path) -> FsResult<()> {
673+
self.check_sync_api_allowed("link_sync")?;
674+
639675
let oldpath_matches = oldpath.starts_with(&self.prefix);
640676
let newpath_matches = newpath.starts_with(&self.prefix);
641677
if oldpath_matches || newpath_matches {
@@ -696,6 +732,8 @@ where
696732
newpath: &Path,
697733
file_type: Option<FsFileType>,
698734
) -> FsResult<()> {
735+
self.check_sync_api_allowed("symlink_sync")?;
736+
699737
let oldpath_matches = oldpath.starts_with(&self.prefix);
700738
let newpath_matches = newpath.starts_with(&self.prefix);
701739
if oldpath_matches || newpath_matches {
@@ -754,6 +792,7 @@ where
754792
}
755793

756794
fn read_link_sync(&self, path: &Path) -> FsResult<PathBuf> {
795+
self.check_sync_api_allowed("read_link_sync")?;
757796
if path.starts_with(&self.prefix) {
758797
self
759798
.fs
@@ -781,6 +820,7 @@ where
781820
}
782821

783822
fn truncate_sync(&self, path: &Path, len: u64) -> FsResult<()> {
823+
self.check_sync_api_allowed("truncate_sync")?;
784824
if path.starts_with(&self.prefix) {
785825
self
786826
.fs
@@ -818,6 +858,7 @@ where
818858
mtime_secs: i64,
819859
mtime_nanos: u32,
820860
) -> FsResult<()> {
861+
self.check_sync_api_allowed("utime_sync")?;
821862
if path.starts_with(&self.prefix) {
822863
self.fs.utime_sync(
823864
path.strip_prefix(&self.prefix).unwrap(),
@@ -872,6 +913,7 @@ where
872913
mtime_secs: i64,
873914
mtime_nanos: u32,
874915
) -> FsResult<()> {
916+
self.check_sync_api_allowed("lutime_sync")?;
875917
if path.starts_with(&self.prefix) {
876918
self.fs.lutime_sync(
877919
path.strip_prefix(&self.prefix).unwrap(),
@@ -925,6 +967,7 @@ where
925967
access_check: Option<AccessCheckCb>,
926968
data: &[u8],
927969
) -> FsResult<()> {
970+
self.check_sync_api_allowed("write_file_sync")?;
928971
if path.starts_with(&self.prefix) {
929972
self.fs.write_file_sync(
930973
path.strip_prefix(&self.prefix).unwrap(),
@@ -970,6 +1013,7 @@ where
9701013
path: &Path,
9711014
access_check: Option<AccessCheckCb>,
9721015
) -> FsResult<Cow<'static, [u8]>> {
1016+
self.check_sync_api_allowed("read_file_sync")?;
9731017
if path.starts_with(&self.prefix) {
9741018
self
9751019
.fs
@@ -1004,6 +1048,9 @@ where
10041048
}
10051049

10061050
fn is_file_sync(&self, path: &Path) -> bool {
1051+
if self.check_sync_api_allowed("is_file_sync").is_err() {
1052+
return false;
1053+
}
10071054
if path.starts_with(&self.prefix) {
10081055
self
10091056
.fs
@@ -1018,6 +1065,9 @@ where
10181065
}
10191066

10201067
fn is_dir_sync(&self, path: &Path) -> bool {
1068+
if self.check_sync_api_allowed("is_dir_sync").is_err() {
1069+
return false;
1070+
}
10211071
if path.starts_with(&self.prefix) {
10221072
self
10231073
.fs
@@ -1032,6 +1082,9 @@ where
10321082
}
10331083

10341084
fn exists_sync(&self, path: &Path) -> bool {
1085+
if self.check_sync_api_allowed("exists_sync").is_err() {
1086+
return false;
1087+
}
10351088
if path.starts_with(&self.prefix) {
10361089
self
10371090
.fs
@@ -1050,6 +1103,7 @@ where
10501103
path: &Path,
10511104
access_check: Option<AccessCheckCb>,
10521105
) -> FsResult<Cow<'static, str>> {
1106+
self.check_sync_api_allowed("read_text_file_lossy_sync")?;
10531107
if path.starts_with(&self.prefix) {
10541108
self.fs.read_text_file_lossy_sync(
10551109
path.strip_prefix(&self.prefix).unwrap(),
@@ -1084,3 +1138,22 @@ where
10841138
}
10851139
}
10861140
}
1141+
1142+
impl<FileSystem> PrefixFs<FileSystem> {
1143+
fn check_sync_api_allowed(&self, name: &'static str) -> FsResult<()> {
1144+
if !self.check_sync_api {
1145+
return Ok(());
1146+
}
1147+
let Some(state) = self.runtime_state.as_ref() else {
1148+
return Ok(());
1149+
};
1150+
1151+
if state.is_init() {
1152+
Ok(())
1153+
} else {
1154+
Err(FsError::Io(io::Error::other(anyhow!(format!(
1155+
"invoking {name} is not allowed in the current context"
1156+
)))))
1157+
}
1158+
}
1159+
}

0 commit comments

Comments
 (0)