summaryrefslogtreecommitdiff
path: root/cli/ops/fs.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2020-08-28 17:08:24 +0200
committerGitHub <noreply@github.com>2020-08-28 17:08:24 +0200
commit7e946858a4a0a03c1461590c6fc8a315738a627a (patch)
tree5a6a391fead573b85fb905bb5c4ea8287dc18d13 /cli/ops/fs.rs
parent31f32ed8c4082d36ad2a4ea460366c0d57a5ddbc (diff)
refactor: migrate ops to new dispatch wrapper (#7118)
Diffstat (limited to 'cli/ops/fs.rs')
-rw-r--r--cli/ops/fs.rs1163
1 files changed, 874 insertions, 289 deletions
diff --git a/cli/ops/fs.rs b/cli/ops/fs.rs
index 28b2a7e55..3b8946057 100644
--- a/cli/ops/fs.rs
+++ b/cli/ops/fs.rs
@@ -1,21 +1,20 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// Some deserializer fields are only used on Unix and Windows build fails without it
-use super::dispatch_json::{blocking_json, Deserialize, JsonOp, Value};
+use super::dispatch_json::{Deserialize, Value};
use super::io::std_file_resource;
use super::io::{FileMetadata, StreamResource, StreamResourceHolder};
use crate::ops::dispatch_json::JsonResult;
use crate::state::State;
use deno_core::BufVec;
use deno_core::CoreIsolate;
-use deno_core::CoreIsolateState;
use deno_core::ErrBox;
use deno_core::ResourceTable;
use deno_core::ZeroCopyBuf;
-use futures::future::FutureExt;
use std::cell::RefCell;
use std::convert::From;
use std::env::{current_dir, set_current_dir, temp_dir};
use std::io;
+use std::io::{Seek, SeekFrom};
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::time::SystemTime;
@@ -29,30 +28,157 @@ pub fn init(i: &mut CoreIsolate, s: &Rc<State>) {
i.register_op("op_open_sync", s.stateful_json_op_sync(t, op_open_sync));
i.register_op("op_open_async", s.stateful_json_op_async(t, op_open_async));
- i.register_op("op_seek", s.stateful_json_op2(op_seek));
- i.register_op("op_fdatasync", s.stateful_json_op2(op_fdatasync));
- i.register_op("op_fsync", s.stateful_json_op2(op_fsync));
- i.register_op("op_fstat", s.stateful_json_op2(op_fstat));
- i.register_op("op_umask", s.stateful_json_op(op_umask));
- i.register_op("op_chdir", s.stateful_json_op(op_chdir));
- i.register_op("op_mkdir", s.stateful_json_op(op_mkdir));
- i.register_op("op_chmod", s.stateful_json_op(op_chmod));
- i.register_op("op_chown", s.stateful_json_op(op_chown));
- i.register_op("op_remove", s.stateful_json_op(op_remove));
- i.register_op("op_copy_file", s.stateful_json_op(op_copy_file));
- i.register_op("op_stat", s.stateful_json_op(op_stat));
- i.register_op("op_realpath", s.stateful_json_op(op_realpath));
- i.register_op("op_read_dir", s.stateful_json_op(op_read_dir));
- i.register_op("op_rename", s.stateful_json_op(op_rename));
- i.register_op("op_link", s.stateful_json_op(op_link));
- i.register_op("op_symlink", s.stateful_json_op(op_symlink));
- i.register_op("op_read_link", s.stateful_json_op(op_read_link));
- i.register_op("op_ftruncate", s.stateful_json_op2(op_ftruncate));
- i.register_op("op_truncate", s.stateful_json_op(op_truncate));
- i.register_op("op_make_temp_dir", s.stateful_json_op(op_make_temp_dir));
- i.register_op("op_make_temp_file", s.stateful_json_op(op_make_temp_file));
- i.register_op("op_cwd", s.stateful_json_op(op_cwd));
- i.register_op("op_utime", s.stateful_json_op(op_utime));
+ i.register_op("op_seek_sync", s.stateful_json_op_sync(t, op_seek_sync));
+ i.register_op("op_seek_async", s.stateful_json_op_async(t, op_seek_async));
+
+ i.register_op(
+ "op_fdatasync_sync",
+ s.stateful_json_op_sync(t, op_fdatasync_sync),
+ );
+ i.register_op(
+ "op_fdatasync_async",
+ s.stateful_json_op_async(t, op_fdatasync_async),
+ );
+
+ i.register_op("op_fsync_sync", s.stateful_json_op_sync(t, op_fsync_sync));
+ i.register_op(
+ "op_fsync_async",
+ s.stateful_json_op_async(t, op_fsync_async),
+ );
+
+ i.register_op("op_fstat_sync", s.stateful_json_op_sync(t, op_fstat_sync));
+ i.register_op(
+ "op_fstat_async",
+ s.stateful_json_op_async(t, op_fstat_async),
+ );
+
+ i.register_op("op_umask", s.stateful_json_op_sync(t, op_umask));
+ i.register_op("op_chdir", s.stateful_json_op_sync(t, op_chdir));
+
+ i.register_op("op_mkdir_sync", s.stateful_json_op_sync(t, op_mkdir_sync));
+ i.register_op(
+ "op_mkdir_async",
+ s.stateful_json_op_async(t, op_mkdir_async),
+ );
+
+ i.register_op("op_chmod_sync", s.stateful_json_op_sync(t, op_chmod_sync));
+ i.register_op(
+ "op_chmod_async",
+ s.stateful_json_op_async(t, op_chmod_async),
+ );
+
+ i.register_op("op_chown_sync", s.stateful_json_op_sync(t, op_chown_sync));
+ i.register_op(
+ "op_chown_async",
+ s.stateful_json_op_async(t, op_chown_async),
+ );
+
+ i.register_op("op_remove_sync", s.stateful_json_op_sync(t, op_remove_sync));
+ i.register_op(
+ "op_remove_async",
+ s.stateful_json_op_async(t, op_remove_async),
+ );
+
+ i.register_op(
+ "op_copy_file_sync",
+ s.stateful_json_op_sync(t, op_copy_file_sync),
+ );
+ i.register_op(
+ "op_copy_file_async",
+ s.stateful_json_op_async(t, op_copy_file_async),
+ );
+
+ i.register_op("op_stat_sync", s.stateful_json_op_sync(t, op_stat_sync));
+ i.register_op("op_stat_async", s.stateful_json_op_async(t, op_stat_async));
+
+ i.register_op(
+ "op_realpath_sync",
+ s.stateful_json_op_sync(t, op_realpath_sync),
+ );
+ i.register_op(
+ "op_realpath_async",
+ s.stateful_json_op_async(t, op_realpath_async),
+ );
+
+ i.register_op(
+ "op_read_dir_sync",
+ s.stateful_json_op_sync(t, op_read_dir_sync),
+ );
+ i.register_op(
+ "op_read_dir_async",
+ s.stateful_json_op_async(t, op_read_dir_async),
+ );
+
+ i.register_op("op_rename_sync", s.stateful_json_op_sync(t, op_rename_sync));
+ i.register_op(
+ "op_rename_async",
+ s.stateful_json_op_async(t, op_rename_async),
+ );
+
+ i.register_op("op_link_sync", s.stateful_json_op_sync(t, op_link_sync));
+ i.register_op("op_link_async", s.stateful_json_op_async(t, op_link_async));
+
+ i.register_op(
+ "op_symlink_sync",
+ s.stateful_json_op_sync(t, op_symlink_sync),
+ );
+ i.register_op(
+ "op_symlink_async",
+ s.stateful_json_op_async(t, op_symlink_async),
+ );
+
+ i.register_op(
+ "op_read_link_sync",
+ s.stateful_json_op_sync(t, op_read_link_sync),
+ );
+ i.register_op(
+ "op_read_link_async",
+ s.stateful_json_op_async(t, op_read_link_async),
+ );
+
+ i.register_op(
+ "op_ftruncate_sync",
+ s.stateful_json_op_sync(t, op_ftruncate_sync),
+ );
+ i.register_op(
+ "op_ftruncate_async",
+ s.stateful_json_op_async(t, op_ftruncate_async),
+ );
+
+ i.register_op(
+ "op_truncate_sync",
+ s.stateful_json_op_sync(t, op_truncate_sync),
+ );
+ i.register_op(
+ "op_truncate_async",
+ s.stateful_json_op_async(t, op_truncate_async),
+ );
+
+ i.register_op(
+ "op_make_temp_dir_sync",
+ s.stateful_json_op_sync(t, op_make_temp_dir_sync),
+ );
+ i.register_op(
+ "op_make_temp_dir_async",
+ s.stateful_json_op_async(t, op_make_temp_dir_async),
+ );
+
+ i.register_op(
+ "op_make_temp_file_sync",
+ s.stateful_json_op_sync(t, op_make_temp_file_sync),
+ );
+ i.register_op(
+ "op_make_temp_file_async",
+ s.stateful_json_op_async(t, op_make_temp_file_async),
+ );
+
+ i.register_op("op_cwd", s.stateful_json_op_sync(t, op_cwd));
+
+ i.register_op("op_utime_sync", s.stateful_json_op_sync(t, op_utime_sync));
+ i.register_op(
+ "op_utime_async",
+ s.stateful_json_op_async(t, op_utime_async),
+ );
}
fn into_string(s: std::ffi::OsString) -> Result<String, ErrBox> {
@@ -165,19 +291,12 @@ async fn op_open_async(
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct SeekArgs {
- promise_id: Option<u64>,
rid: i32,
offset: i64,
whence: i32,
}
-fn op_seek(
- isolate_state: &mut CoreIsolateState,
- _state: &Rc<State>,
- args: Value,
- _zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
- use std::io::{Seek, SeekFrom};
+fn seek_helper(args: Value) -> Result<(u32, SeekFrom), ErrBox> {
let args: SeekArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
let offset = args.offset;
@@ -192,154 +311,171 @@ fn op_seek(
}
};
- let resource_table = isolate_state.resource_table.clone();
- let is_sync = args.promise_id.is_none();
+ Ok((rid, seek_from))
+}
- if is_sync {
- let mut resource_table = resource_table.borrow_mut();
- let pos = std_file_resource(&mut resource_table, rid, |r| match r {
- Ok(std_file) => std_file.seek(seek_from).map_err(ErrBox::from),
- Err(_) => Err(ErrBox::type_error("cannot seek on this type of resource")),
- })?;
- Ok(JsonOp::Sync(json!(pos)))
- } else {
- // TODO(ry) This is a fake async op. We need to use poll_fn,
- // tokio::fs::File::start_seek and tokio::fs::File::poll_complete
- let fut = async move {
- let mut resource_table = resource_table.borrow_mut();
- let pos = std_file_resource(&mut resource_table, rid, |r| match r {
- Ok(std_file) => std_file.seek(seek_from).map_err(ErrBox::from),
- Err(_) => {
- Err(ErrBox::type_error("cannot seek on this type of resource"))
- }
- })?;
- Ok(json!(pos))
- };
- Ok(JsonOp::Async(fut.boxed_local()))
- }
+fn op_seek_sync(
+ _state: &State,
+ resource_table: &mut ResourceTable,
+ args: Value,
+ _zero_copy: &mut [ZeroCopyBuf],
+) -> Result<Value, ErrBox> {
+ let (rid, seek_from) = seek_helper(args)?;
+ let pos = std_file_resource(resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.seek(seek_from).map_err(ErrBox::from),
+ Err(_) => Err(ErrBox::type_error(
+ "cannot seek on this type of resource".to_string(),
+ )),
+ })?;
+ Ok(json!(pos))
+}
+
+async fn op_seek_async(
+ _state: Rc<State>,
+ resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
+ let (rid, seek_from) = seek_helper(args)?;
+ // TODO(ry) This is a fake async op. We need to use poll_fn,
+ // tokio::fs::File::start_seek and tokio::fs::File::poll_complete
+ let mut resource_table = resource_table.borrow_mut();
+ let pos = std_file_resource(&mut resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.seek(seek_from).map_err(ErrBox::from),
+ Err(_) => Err(ErrBox::type_error(
+ "cannot seek on this type of resource".to_string(),
+ )),
+ })?;
+ Ok(json!(pos))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct FdatasyncArgs {
- promise_id: Option<u64>,
rid: i32,
}
-fn op_fdatasync(
- isolate_state: &mut CoreIsolateState,
- state: &Rc<State>,
+fn op_fdatasync_sync(
+ state: &State,
+ resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
state.check_unstable("Deno.fdatasync");
let args: FdatasyncArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
+ std_file_resource(resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.sync_data().map_err(ErrBox::from),
+ Err(_) => Err(ErrBox::type_error(
+ "cannot sync this type of resource".to_string(),
+ )),
+ })?;
+ Ok(json!({}))
+}
- let resource_table = isolate_state.resource_table.clone();
- let is_sync = args.promise_id.is_none();
-
- if is_sync {
- let mut resource_table = resource_table.borrow_mut();
- std_file_resource(&mut resource_table, rid, |r| match r {
- Ok(std_file) => std_file.sync_data().map_err(ErrBox::from),
- Err(_) => Err(ErrBox::type_error("cannot sync this type of resource")),
- })?;
- Ok(JsonOp::Sync(json!({})))
- } else {
- let fut = async move {
- let mut resource_table = resource_table.borrow_mut();
- std_file_resource(&mut resource_table, rid, |r| match r {
- Ok(std_file) => std_file.sync_data().map_err(ErrBox::from),
- Err(_) => Err(ErrBox::type_error("cannot sync this type of resource")),
- })?;
- Ok(json!({}))
- };
- Ok(JsonOp::Async(fut.boxed_local()))
- }
+async fn op_fdatasync_async(
+ state: Rc<State>,
+ resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
+ state.check_unstable("Deno.fdatasync");
+ let args: FdatasyncArgs = serde_json::from_value(args)?;
+ let rid = args.rid as u32;
+ let mut resource_table = resource_table.borrow_mut();
+ std_file_resource(&mut resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.sync_data().map_err(ErrBox::from),
+ Err(_) => Err(ErrBox::type_error(
+ "cannot sync this type of resource".to_string(),
+ )),
+ })?;
+ Ok(json!({}))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct FsyncArgs {
- promise_id: Option<u64>,
rid: i32,
}
-fn op_fsync(
- isolate_state: &mut CoreIsolateState,
- state: &Rc<State>,
+fn op_fsync_sync(
+ state: &State,
+ resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
state.check_unstable("Deno.fsync");
let args: FsyncArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
+ std_file_resource(resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.sync_all().map_err(ErrBox::from),
+ Err(_) => Err(ErrBox::type_error(
+ "cannot sync this type of resource".to_string(),
+ )),
+ })?;
+ Ok(json!({}))
+}
- let resource_table = isolate_state.resource_table.clone();
- let is_sync = args.promise_id.is_none();
-
- if is_sync {
- let mut resource_table = resource_table.borrow_mut();
- std_file_resource(&mut resource_table, rid, |r| match r {
- Ok(std_file) => std_file.sync_all().map_err(ErrBox::from),
- Err(_) => Err(ErrBox::type_error("cannot sync this type of resource")),
- })?;
- Ok(JsonOp::Sync(json!({})))
- } else {
- let fut = async move {
- let mut resource_table = resource_table.borrow_mut();
- std_file_resource(&mut resource_table, rid, |r| match r {
- Ok(std_file) => std_file.sync_all().map_err(ErrBox::from),
- Err(_) => Err(ErrBox::type_error("cannot sync this type of resource")),
- })?;
- Ok(json!({}))
- };
- Ok(JsonOp::Async(fut.boxed_local()))
- }
+async fn op_fsync_async(
+ state: Rc<State>,
+ resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
+ state.check_unstable("Deno.fsync");
+ let args: FsyncArgs = serde_json::from_value(args)?;
+ let rid = args.rid as u32;
+ let mut resource_table = resource_table.borrow_mut();
+ std_file_resource(&mut resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.sync_all().map_err(ErrBox::from),
+ Err(_) => Err(ErrBox::type_error(
+ "cannot sync this type of resource".to_string(),
+ )),
+ })?;
+ Ok(json!({}))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct FstatArgs {
- promise_id: Option<u64>,
rid: i32,
}
-fn op_fstat(
- isolate_state: &mut CoreIsolateState,
- state: &Rc<State>,
+fn op_fstat_sync(
+ state: &State,
+ resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
state.check_unstable("Deno.fstat");
let args: FstatArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
+ let metadata = std_file_resource(resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.metadata().map_err(ErrBox::from),
+ Err(_) => Err(ErrBox::type_error(
+ "cannot stat this type of resource".to_string(),
+ )),
+ })?;
+ Ok(get_stat_json(metadata).unwrap())
+}
- let resource_table = isolate_state.resource_table.clone();
- let is_sync = args.promise_id.is_none();
-
- if is_sync {
- let mut resource_table = resource_table.borrow_mut();
- let metadata = std_file_resource(&mut resource_table, rid, |r| match r {
- Ok(std_file) => std_file.metadata().map_err(ErrBox::from),
- Err(_) => Err(ErrBox::type_error("cannot stat this type of resource")),
- })?;
- Ok(JsonOp::Sync(get_stat_json(metadata).unwrap()))
- } else {
- let fut = async move {
- let mut resource_table = resource_table.borrow_mut();
- let metadata =
- std_file_resource(&mut resource_table, rid, |r| match r {
- Ok(std_file) => std_file.metadata().map_err(ErrBox::from),
- Err(_) => {
- Err(ErrBox::type_error("cannot stat this type of resource"))
- }
- })?;
- Ok(get_stat_json(metadata).unwrap())
- };
- Ok(JsonOp::Async(fut.boxed_local()))
- }
+async fn op_fstat_async(
+ state: Rc<State>,
+ resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
+ state.check_unstable("Deno.fstat");
+ let args: FstatArgs = serde_json::from_value(args)?;
+ let rid = args.rid as u32;
+ let mut resource_table = resource_table.borrow_mut();
+ let metadata = std_file_resource(&mut resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.metadata().map_err(ErrBox::from),
+ Err(_) => Err(ErrBox::type_error(
+ "cannot stat this type of resource".to_string(),
+ )),
+ })?;
+ Ok(get_stat_json(metadata).unwrap())
}
#[derive(Deserialize)]
@@ -348,10 +484,11 @@ struct UmaskArgs {
}
fn op_umask(
- state: &Rc<State>,
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
state.check_unstable("Deno.umask");
let args: UmaskArgs = serde_json::from_value(args)?;
// TODO implement umask for Windows
@@ -376,7 +513,7 @@ fn op_umask(
let _ = umask(prev);
prev
};
- Ok(JsonOp::Sync(json!(r.bits() as u32)))
+ Ok(json!(r.bits() as u32))
}
}
@@ -386,39 +523,59 @@ struct ChdirArgs {
}
fn op_chdir(
- state: &Rc<State>,
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
let args: ChdirArgs = serde_json::from_value(args)?;
let d = PathBuf::from(&args.directory);
state.check_read(&d)?;
set_current_dir(&d)?;
- Ok(JsonOp::Sync(json!({})))
+ Ok(json!({}))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct MkdirArgs {
- promise_id: Option<u64>,
path: String,
recursive: bool,
mode: Option<u32>,
}
-fn op_mkdir(
- state: &Rc<State>,
+fn op_mkdir_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
let args: MkdirArgs = serde_json::from_value(args)?;
let path = Path::new(&args.path).to_path_buf();
let mode = args.mode.unwrap_or(0o777) & 0o777;
-
state.check_write(&path)?;
+ debug!("op_mkdir {} {:o} {}", path.display(), mode, args.recursive);
+ let mut builder = std::fs::DirBuilder::new();
+ builder.recursive(args.recursive);
+ #[cfg(unix)]
+ {
+ use std::os::unix::fs::DirBuilderExt;
+ builder.mode(mode);
+ }
+ builder.create(path)?;
+ Ok(json!({}))
+}
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
+async fn op_mkdir_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
+ let args: MkdirArgs = serde_json::from_value(args)?;
+ let path = Path::new(&args.path).to_path_buf();
+ let mode = args.mode.unwrap_or(0o777) & 0o777;
+ state.check_write(&path)?;
+ tokio::task::spawn_blocking(move || {
debug!("op_mkdir {} {:o} {}", path.display(), mode, args.recursive);
let mut builder = std::fs::DirBuilder::new();
builder.recursive(args.recursive);
@@ -430,30 +587,57 @@ fn op_mkdir(
builder.create(path)?;
Ok(json!({}))
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct ChmodArgs {
- promise_id: Option<u64>,
path: String,
mode: u32,
}
-fn op_chmod(
- state: &Rc<State>,
+fn op_chmod_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
let args: ChmodArgs = serde_json::from_value(args)?;
let path = Path::new(&args.path).to_path_buf();
let mode = args.mode & 0o777;
state.check_write(&path)?;
+ debug!("op_chmod_sync {} {:o}", path.display(), mode);
+ #[cfg(unix)]
+ {
+ use std::os::unix::fs::PermissionsExt;
+ let permissions = PermissionsExt::from_mode(mode);
+ std::fs::set_permissions(&path, permissions)?;
+ Ok(json!({}))
+ }
+ // TODO Implement chmod for Windows (#4357)
+ #[cfg(not(unix))]
+ {
+ // Still check file/dir exists on Windows
+ let _metadata = std::fs::metadata(&path)?;
+ Err(ErrBox::error("Not implemented"))
+ }
+}
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_chmod {} {:o}", path.display(), mode);
+async fn op_chmod_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
+ let args: ChmodArgs = serde_json::from_value(args)?;
+ let path = Path::new(&args.path).to_path_buf();
+ let mode = args.mode & 0o777;
+ state.check_write(&path)?;
+ tokio::task::spawn_blocking(move || {
+ debug!("op_chmod_async {} {:o}", path.display(), mode);
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
@@ -469,30 +653,64 @@ fn op_chmod(
Err(ErrBox::not_supported())
}
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct ChownArgs {
- promise_id: Option<u64>,
path: String,
uid: Option<u32>,
gid: Option<u32>,
}
-fn op_chown(
- state: &Rc<State>,
+fn op_chown_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
let args: ChownArgs = serde_json::from_value(args)?;
let path = Path::new(&args.path).to_path_buf();
-
state.check_write(&path)?;
+ debug!(
+ "op_chown_sync {} {:?} {:?}",
+ path.display(),
+ args.uid,
+ args.gid,
+ );
+ #[cfg(unix)]
+ {
+ use nix::unistd::{chown, Gid, Uid};
+ let nix_uid = args.uid.map(Uid::from_raw);
+ let nix_gid = args.gid.map(Gid::from_raw);
+ chown(&path, nix_uid, nix_gid)?;
+ Ok(json!({}))
+ }
+ // TODO Implement chown for Windows
+ #[cfg(not(unix))]
+ {
+ Err(ErrBox::error("Not implemented"))
+ }
+}
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_chown {} {:?} {:?}", path.display(), args.uid, args.gid,);
+async fn op_chown_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
+ let args: ChownArgs = serde_json::from_value(args)?;
+ let path = Path::new(&args.path).to_path_buf();
+ state.check_write(&path)?;
+ tokio::task::spawn_blocking(move || {
+ debug!(
+ "op_chown_async {} {:?} {:?}",
+ path.display(),
+ args.uid,
+ args.gid,
+ );
#[cfg(unix)]
{
use nix::unistd::{chown, Gid, Uid};
@@ -505,35 +723,80 @@ fn op_chown(
#[cfg(not(unix))]
Err(ErrBox::not_supported())
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct RemoveArgs {
- promise_id: Option<u64>,
path: String,
recursive: bool,
}
-fn op_remove(
- state: &Rc<State>,
+fn op_remove_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ let args: RemoveArgs = serde_json::from_value(args)?;
+ let path = PathBuf::from(&args.path);
+ let recursive = args.recursive;
+
+ state.check_write(&path)?;
+
+ #[cfg(not(unix))]
+ use std::os::windows::prelude::MetadataExt;
+
+ let metadata = std::fs::symlink_metadata(&path)?;
+
+ debug!("op_remove_sync {} {}", path.display(), recursive);
+ let file_type = metadata.file_type();
+ if file_type.is_file() {
+ std::fs::remove_file(&path)?;
+ } else if recursive {
+ std::fs::remove_dir_all(&path)?;
+ } else if file_type.is_symlink() {
+ #[cfg(unix)]
+ std::fs::remove_file(&path)?;
+ #[cfg(not(unix))]
+ {
+ use winapi::um::winnt::FILE_ATTRIBUTE_DIRECTORY;
+ if metadata.file_attributes() & FILE_ATTRIBUTE_DIRECTORY != 0 {
+ std::fs::remove_dir(&path)?;
+ } else {
+ std::fs::remove_file(&path)?;
+ }
+ }
+ } else if file_type.is_dir() {
+ std::fs::remove_dir(&path)?;
+ } else {
+ // pipes, sockets, etc...
+ std::fs::remove_file(&path)?;
+ }
+ Ok(json!({}))
+}
+
+async fn op_remove_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
let args: RemoveArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
let recursive = args.recursive;
state.check_write(&path)?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
+ tokio::task::spawn_blocking(move || {
#[cfg(not(unix))]
use std::os::windows::prelude::MetadataExt;
let metadata = std::fs::symlink_metadata(&path)?;
- debug!("op_remove {} {}", path.display(), recursive);
+ debug!("op_remove_async {} {}", path.display(), recursive);
let file_type = metadata.file_type();
if file_type.is_file() {
std::fs::remove_file(&path)?;
@@ -559,21 +822,49 @@ fn op_remove(
}
Ok(json!({}))
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct CopyFileArgs {
- promise_id: Option<u64>,
from: String,
to: String,
}
-fn op_copy_file(
- state: &Rc<State>,
+fn op_copy_file_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ let args: CopyFileArgs = serde_json::from_value(args)?;
+ let from = PathBuf::from(&args.from);
+ let to = PathBuf::from(&args.to);
+
+ state.check_read(&from)?;
+ state.check_write(&to)?;
+
+ debug!("op_copy_file_sync {} {}", from.display(), to.display());
+ // On *nix, Rust reports non-existent `from` as ErrorKind::InvalidInput
+ // See https://github.com/rust-lang/rust/issues/54800
+ // Once the issue is resolved, we should remove this workaround.
+ if cfg!(unix) && !from.is_file() {
+ return Err(ErrBox::new("NotFound", "File not found"));
+ }
+
+ // returns size of from as u64 (we ignore)
+ std::fs::copy(&from, &to)?;
+ Ok(json!({}))
+}
+
+async fn op_copy_file_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
let args: CopyFileArgs = serde_json::from_value(args)?;
let from = PathBuf::from(&args.from);
let to = PathBuf::from(&args.to);
@@ -581,9 +872,8 @@ fn op_copy_file(
state.check_read(&from)?;
state.check_write(&to)?;
- debug!("op_copy_file {} {}", from.display(), to.display());
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
+ debug!("op_copy_file_async {} {}", from.display(), to.display());
+ tokio::task::spawn_blocking(move || {
// On *nix, Rust reports non-existent `from` as ErrorKind::InvalidInput
// See https://github.com/rust-lang/rust/issues/54800
// Once the issue is resolved, we should remove this workaround.
@@ -595,6 +885,8 @@ fn op_copy_file(
std::fs::copy(&from, &to)?;
Ok(json!({}))
})
+ .await
+ .unwrap()
}
fn to_msec(maybe_time: Result<SystemTime, io::Error>) -> serde_json::Value {
@@ -658,25 +950,43 @@ fn get_stat_json(metadata: std::fs::Metadata) -> JsonResult {
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct StatArgs {
- promise_id: Option<u64>,
path: String,
lstat: bool,
}
-fn op_stat(
- state: &Rc<State>,
+fn op_stat_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ let args: StatArgs = serde_json::from_value(args)?;
+ let path = PathBuf::from(&args.path);
+ let lstat = args.lstat;
+ state.check_read(&path)?;
+ debug!("op_stat_sync {} {}", path.display(), lstat);
+ let metadata = if lstat {
+ std::fs::symlink_metadata(&path)?
+ } else {
+ std::fs::metadata(&path)?
+ };
+ get_stat_json(metadata)
+}
+
+async fn op_stat_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
let args: StatArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
let lstat = args.lstat;
state.check_read(&path)?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_stat {} {}", path.display(), lstat);
+ tokio::task::spawn_blocking(move || {
+ debug!("op_stat_async {} {}", path.display(), lstat);
let metadata = if lstat {
std::fs::symlink_metadata(&path)?
} else {
@@ -684,20 +994,22 @@ fn op_stat(
};
get_stat_json(metadata)
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct RealpathArgs {
- promise_id: Option<u64>,
path: String,
}
-fn op_realpath(
- state: &Rc<State>,
+fn op_realpath_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
let args: RealpathArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
@@ -706,9 +1018,34 @@ fn op_realpath(
state.check_read_blind(&current_dir()?, "CWD")?;
}
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_realpath {}", path.display());
+ debug!("op_realpath_sync {}", path.display());
+ // corresponds to the realpath on Unix and
+ // CreateFile and GetFinalPathNameByHandle on Windows
+ let realpath = std::fs::canonicalize(&path)?;
+ let mut realpath_str =
+ into_string(realpath.into_os_string())?.replace("\\", "/");
+ if cfg!(windows) {
+ realpath_str = realpath_str.trim_start_matches("//?/").to_string();
+ }
+ Ok(json!(realpath_str))
+}
+
+async fn op_realpath_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
+ let args: RealpathArgs = serde_json::from_value(args)?;
+ let path = PathBuf::from(&args.path);
+
+ state.check_read(&path)?;
+ if path.is_relative() {
+ state.check_read_blind(&current_dir()?, "CWD")?;
+ }
+
+ tokio::task::spawn_blocking(move || {
+ debug!("op_realpath_async {}", path.display());
// corresponds to the realpath on Unix and
// CreateFile and GetFinalPathNameByHandle on Windows
let realpath = std::fs::canonicalize(&path)?;
@@ -719,28 +1056,62 @@ fn op_realpath(
}
Ok(json!(realpath_str))
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct ReadDirArgs {
- promise_id: Option<u64>,
path: String,
}
-fn op_read_dir(
- state: &Rc<State>,
+fn op_read_dir_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ let args: ReadDirArgs = serde_json::from_value(args)?;
+ let path = PathBuf::from(&args.path);
+
+ state.check_read(&path)?;
+
+ debug!("op_read_dir_sync {}", path.display());
+ let entries: Vec<_> = std::fs::read_dir(path)?
+ .filter_map(|entry| {
+ let entry = entry.unwrap();
+ let file_type = entry.file_type().unwrap();
+ // Not all filenames can be encoded as UTF-8. Skip those for now.
+ if let Ok(name) = into_string(entry.file_name()) {
+ Some(json!({
+ "name": name,
+ "isFile": file_type.is_file(),
+ "isDirectory": file_type.is_dir(),
+ "isSymlink": file_type.is_symlink()
+ }))
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ Ok(json!({ "entries": entries }))
+}
+
+async fn op_read_dir_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
let args: ReadDirArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
state.check_read(&path)?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_read_dir {}", path.display());
+ tokio::task::spawn_blocking(move || {
+ debug!("op_read_dir_async {}", path.display());
let entries: Vec<_> = std::fs::read_dir(path)?
.filter_map(|entry| {
let entry = entry.unwrap();
@@ -761,21 +1132,41 @@ fn op_read_dir(
Ok(json!({ "entries": entries }))
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct RenameArgs {
- promise_id: Option<u64>,
oldpath: String,
newpath: String,
}
-fn op_rename(
- state: &Rc<State>,
+fn op_rename_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ let args: RenameArgs = serde_json::from_value(args)?;
+ let oldpath = PathBuf::from(&args.oldpath);
+ let newpath = PathBuf::from(&args.newpath);
+
+ state.check_read(&oldpath)?;
+ state.check_write(&oldpath)?;
+ state.check_write(&newpath)?;
+ debug!("op_rename_sync {} {}", oldpath.display(), newpath.display());
+ std::fs::rename(&oldpath, &newpath)?;
+ Ok(json!({}))
+}
+
+async fn op_rename_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
let args: RenameArgs = serde_json::from_value(args)?;
let oldpath = PathBuf::from(&args.oldpath);
let newpath = PathBuf::from(&args.newpath);
@@ -784,27 +1175,51 @@ fn op_rename(
state.check_write(&oldpath)?;
state.check_write(&newpath)?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_rename {} {}", oldpath.display(), newpath.display());
+ tokio::task::spawn_blocking(move || {
+ debug!(
+ "op_rename_async {} {}",
+ oldpath.display(),
+ newpath.display()
+ );
std::fs::rename(&oldpath, &newpath)?;
Ok(json!({}))
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct LinkArgs {
- promise_id: Option<u64>,
oldpath: String,
newpath: String,
}
-fn op_link(
- state: &Rc<State>,
+fn op_link_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ state.check_unstable("Deno.link");
+ let args: LinkArgs = serde_json::from_value(args)?;
+ let oldpath = PathBuf::from(&args.oldpath);
+ let newpath = PathBuf::from(&args.newpath);
+
+ state.check_read(&oldpath)?;
+ state.check_write(&newpath)?;
+
+ debug!("op_link_sync {} {}", oldpath.display(), newpath.display());
+ std::fs::hard_link(&oldpath, &newpath)?;
+ Ok(json!({}))
+}
+
+async fn op_link_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
state.check_unstable("Deno.link");
let args: LinkArgs = serde_json::from_value(args)?;
let oldpath = PathBuf::from(&args.oldpath);
@@ -813,18 +1228,18 @@ fn op_link(
state.check_read(&oldpath)?;
state.check_write(&newpath)?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_link {} {}", oldpath.display(), newpath.display());
+ tokio::task::spawn_blocking(move || {
+ debug!("op_link_async {} {}", oldpath.display(), newpath.display());
std::fs::hard_link(&oldpath, &newpath)?;
Ok(json!({}))
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct SymlinkArgs {
- promise_id: Option<u64>,
oldpath: String,
newpath: String,
#[cfg(not(unix))]
@@ -838,11 +1253,67 @@ struct SymlinkOptions {
_type: String,
}
-fn op_symlink(
- state: &Rc<State>,
+fn op_symlink_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ state.check_unstable("Deno.symlink");
+ let args: SymlinkArgs = serde_json::from_value(args)?;
+ let oldpath = PathBuf::from(&args.oldpath);
+ let newpath = PathBuf::from(&args.newpath);
+
+ state.check_write(&newpath)?;
+
+ debug!(
+ "op_symlink_sync {} {}",
+ oldpath.display(),
+ newpath.display()
+ );
+ #[cfg(unix)]
+ {
+ use std::os::unix::fs::symlink;
+ symlink(&oldpath, &newpath)?;
+ Ok(json!({}))
+ }
+ #[cfg(not(unix))]
+ {
+ use std::os::windows::fs::{symlink_dir, symlink_file};
+
+ match args.options {
+ Some(options) => match options._type.as_ref() {
+ "file" => symlink_file(&oldpath, &newpath)?,
+ "dir" => symlink_dir(&oldpath, &newpath)?,
+ _ => return Err(ErrBox::type_error("unsupported type")),
+ },
+ None => {
+ let old_meta = std::fs::metadata(&oldpath);
+ match old_meta {
+ Ok(metadata) => {
+ if metadata.is_file() {
+ symlink_file(&oldpath, &newpath)?
+ } else if metadata.is_dir() {
+ symlink_dir(&oldpath, &newpath)?
+ }
+ }
+ Err(_) => return Err(ErrBox::type_error(
+ "you must pass a `options` argument for non-existent target path in windows"
+ .to_string(),
+ )),
+ }
+ }
+ };
+ Ok(json!({}))
+ }
+}
+
+async fn op_symlink_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
state.check_unstable("Deno.symlink");
let args: SymlinkArgs = serde_json::from_value(args)?;
let oldpath = PathBuf::from(&args.oldpath);
@@ -850,9 +1321,8 @@ fn op_symlink(
state.check_write(&newpath)?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_symlink {} {}", oldpath.display(), newpath.display());
+ tokio::task::spawn_blocking(move || {
+ debug!("op_symlink_async {} {}", oldpath.display(), newpath.display());
#[cfg(unix)]
{
use std::os::unix::fs::symlink;
@@ -889,106 +1359,141 @@ fn op_symlink(
Ok(json!({}))
}
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct ReadLinkArgs {
- promise_id: Option<u64>,
path: String,
}
-fn op_read_link(
- state: &Rc<State>,
+fn op_read_link_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
let args: ReadLinkArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
state.check_read(&path)?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_read_link {}", path.display());
+ debug!("op_read_link_value {}", path.display());
+ let target = std::fs::read_link(&path)?.into_os_string();
+ let targetstr = into_string(target)?;
+ Ok(json!(targetstr))
+}
+
+async fn op_read_link_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
+ let args: ReadLinkArgs = serde_json::from_value(args)?;
+ let path = PathBuf::from(&args.path);
+
+ state.check_read(&path)?;
+
+ tokio::task::spawn_blocking(move || {
+ debug!("op_read_link_async {}", path.display());
let target = std::fs::read_link(&path)?.into_os_string();
let targetstr = into_string(target)?;
Ok(json!(targetstr))
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct FtruncateArgs {
- promise_id: Option<u64>,
rid: i32,
len: i32,
}
-fn op_ftruncate(
- isolate_state: &mut CoreIsolateState,
- state: &Rc<State>,
+fn op_ftruncate_sync(
+ state: &State,
+ resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
state.check_unstable("Deno.ftruncate");
let args: FtruncateArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
let len = args.len as u64;
+ std_file_resource(resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.set_len(len).map_err(ErrBox::from),
+ Err(_) => Err(ErrBox::type_error("cannot truncate this type of resource")),
+ })?;
+ Ok(json!({}))
+}
- let resource_table = isolate_state.resource_table.clone();
- let is_sync = args.promise_id.is_none();
-
- if is_sync {
- let mut resource_table = resource_table.borrow_mut();
- std_file_resource(&mut resource_table, rid, |r| match r {
- Ok(std_file) => std_file.set_len(len).map_err(ErrBox::from),
- Err(_) => {
- Err(ErrBox::type_error("cannot truncate this type of resource"))
- }
- })?;
- Ok(JsonOp::Sync(json!({})))
- } else {
- let fut = async move {
- let mut resource_table = resource_table.borrow_mut();
- std_file_resource(&mut resource_table, rid, |r| match r {
- Ok(std_file) => std_file.set_len(len).map_err(ErrBox::from),
- Err(_) => {
- Err(ErrBox::type_error("cannot truncate this type of resource"))
- }
- })?;
- Ok(json!({}))
- };
- Ok(JsonOp::Async(fut.boxed_local()))
- }
+async fn op_ftruncate_async(
+ state: Rc<State>,
+ resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
+ state.check_unstable("Deno.ftruncate");
+ let args: FtruncateArgs = serde_json::from_value(args)?;
+ let rid = args.rid as u32;
+ let len = args.len as u64;
+ let mut resource_table = resource_table.borrow_mut();
+ std_file_resource(&mut resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.set_len(len).map_err(ErrBox::from),
+ Err(_) => Err(ErrBox::type_error("cannot truncate this type of resource")),
+ })?;
+ Ok(json!({}))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct TruncateArgs {
- promise_id: Option<u64>,
path: String,
len: u64,
}
-fn op_truncate(
- state: &Rc<State>,
+fn op_truncate_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ let args: TruncateArgs = serde_json::from_value(args)?;
+ let path = PathBuf::from(&args.path);
+ let len = args.len;
+
+ state.check_write(&path)?;
+
+ debug!("op_truncate_sync {} {}", path.display(), len);
+ let f = std::fs::OpenOptions::new().write(true).open(&path)?;
+ f.set_len(len)?;
+ Ok(json!({}))
+}
+
+async fn op_truncate_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
let args: TruncateArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
let len = args.len;
state.check_write(&path)?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_truncate {} {}", path.display(), len);
+ tokio::task::spawn_blocking(move || {
+ debug!("op_truncate_async {} {}", path.display(), len);
let f = std::fs::OpenOptions::new().write(true).open(&path)?;
f.set_len(len)?;
Ok(json!({}))
})
+ .await
+ .unwrap()
}
fn make_temp(
@@ -1039,17 +1544,46 @@ fn make_temp(
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct MakeTempArgs {
- promise_id: Option<u64>,
dir: Option<String>,
prefix: Option<String>,
suffix: Option<String>,
}
-fn op_make_temp_dir(
- state: &Rc<State>,
+fn op_make_temp_dir_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ let args: MakeTempArgs = serde_json::from_value(args)?;
+
+ let dir = args.dir.map(|s| PathBuf::from(&s));
+ let prefix = args.prefix.map(String::from);
+ let suffix = args.suffix.map(String::from);
+
+ state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
+
+ // TODO(piscisaureus): use byte vector for paths, not a string.
+ // See https://github.com/denoland/deno/issues/627.
+ // We can't assume that paths are always valid utf8 strings.
+ let path = make_temp(
+ // Converting Option<String> to Option<&str>
+ dir.as_deref(),
+ prefix.as_deref(),
+ suffix.as_deref(),
+ true,
+ )?;
+ let path_str = into_string(path.into_os_string())?;
+
+ Ok(json!(path_str))
+}
+
+async fn op_make_temp_dir_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
let args: MakeTempArgs = serde_json::from_value(args)?;
let dir = args.dir.map(|s| PathBuf::from(&s));
@@ -1058,8 +1592,7 @@ fn op_make_temp_dir(
state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
+ tokio::task::spawn_blocking(move || {
// TODO(piscisaureus): use byte vector for paths, not a string.
// See https://github.com/denoland/deno/issues/627.
// We can't assume that paths are always valid utf8 strings.
@@ -1074,13 +1607,45 @@ fn op_make_temp_dir(
Ok(json!(path_str))
})
+ .await
+ .unwrap()
}
-fn op_make_temp_file(
- state: &Rc<State>,
+fn op_make_temp_file_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ let args: MakeTempArgs = serde_json::from_value(args)?;
+
+ let dir = args.dir.map(|s| PathBuf::from(&s));
+ let prefix = args.prefix.map(String::from);
+ let suffix = args.suffix.map(String::from);
+
+ state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
+
+ // TODO(piscisaureus): use byte vector for paths, not a string.
+ // See https://github.com/denoland/deno/issues/627.
+ // We can't assume that paths are always valid utf8 strings.
+ let path = make_temp(
+ // Converting Option<String> to Option<&str>
+ dir.as_deref(),
+ prefix.as_deref(),
+ suffix.as_deref(),
+ false,
+ )?;
+ let path_str = into_string(path.into_os_string())?;
+
+ Ok(json!(path_str))
+}
+
+async fn op_make_temp_file_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
let args: MakeTempArgs = serde_json::from_value(args)?;
let dir = args.dir.map(|s| PathBuf::from(&s));
@@ -1089,8 +1654,7 @@ fn op_make_temp_file(
state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
+ tokio::task::spawn_blocking(move || {
// TODO(piscisaureus): use byte vector for paths, not a string.
// See https://github.com/denoland/deno/issues/627.
// We can't assume that paths are always valid utf8 strings.
@@ -1105,22 +1669,41 @@ fn op_make_temp_file(
Ok(json!(path_str))
})
+ .await
+ .unwrap()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct UtimeArgs {
- promise_id: Option<u64>,
path: String,
atime: i64,
mtime: i64,
}
-fn op_utime(
- state: &Rc<State>,
+fn op_utime_sync(
+ state: &State,
+ _resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
+ state.check_unstable("Deno.utime");
+
+ let args: UtimeArgs = serde_json::from_value(args)?;
+ let path = PathBuf::from(&args.path);
+
+ state.check_write(&path)?;
+ debug!("op_utime_sync {} {} {}", args.path, args.atime, args.mtime);
+ utime::set_file_times(args.path, args.atime, args.mtime)?;
+ Ok(json!({}))
+}
+
+async fn op_utime_async(
+ state: Rc<State>,
+ _resource_table: Rc<RefCell<ResourceTable>>,
+ args: Value,
+ _zero_copy: BufVec,
+) -> Result<Value, ErrBox> {
state.check_unstable("Deno.utime");
let args: UtimeArgs = serde_json::from_value(args)?;
@@ -1128,21 +1711,23 @@ fn op_utime(
state.check_write(&path)?;
- let is_sync = args.promise_id.is_none();
- blocking_json(is_sync, move || {
- debug!("op_utime {} {} {}", args.path, args.atime, args.mtime);
+ tokio::task::spawn_blocking(move || {
+ debug!("op_utime_async {} {} {}", args.path, args.atime, args.mtime);
utime::set_file_times(args.path, args.atime, args.mtime)?;
Ok(json!({}))
})
+ .await
+ .unwrap()
}
fn op_cwd(
- state: &Rc<State>,
+ state: &State,
+ _resource_table: &mut ResourceTable,
_args: Value,
_zero_copy: &mut [ZeroCopyBuf],
-) -> Result<JsonOp, ErrBox> {
+) -> Result<Value, ErrBox> {
let path = current_dir()?;
state.check_read_blind(&path, "CWD")?;
let path_str = into_string(path.into_os_string())?;
- Ok(JsonOp::Sync(json!(path_str)))
+ Ok(json!(path_str))
}