diff options
Diffstat (limited to 'cli/ops/files.rs')
-rw-r--r-- | cli/ops/files.rs | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/cli/ops/files.rs b/cli/ops/files.rs new file mode 100644 index 000000000..ce3285623 --- /dev/null +++ b/cli/ops/files.rs @@ -0,0 +1,231 @@ +// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +use crate::deno_error; +use crate::fs as deno_fs; +use crate::msg; +use crate::ops::empty_buf; +use crate::ops::ok_buf; +use crate::ops::serialize_response; +use crate::ops::CliOpResult; +use crate::resources; +use crate::state::ThreadSafeState; +use crate::tokio_write; +use deno::*; +use flatbuffers::FlatBufferBuilder; +use futures::Future; +use std; +use std::convert::From; +use tokio; + +pub fn op_open( + state: &ThreadSafeState, + base: &msg::Base<'_>, + data: Option<PinnedBuf>, +) -> CliOpResult { + assert!(data.is_none()); + let cmd_id = base.cmd_id(); + let inner = base.inner_as_open().unwrap(); + let (filename, filename_) = + deno_fs::resolve_from_cwd(inner.filename().unwrap())?; + let mode = inner.mode().unwrap(); + + let mut open_options = tokio::fs::OpenOptions::new(); + + match mode { + "r" => { + open_options.read(true); + } + "r+" => { + open_options.read(true).write(true); + } + "w" => { + open_options.create(true).write(true).truncate(true); + } + "w+" => { + open_options + .read(true) + .create(true) + .write(true) + .truncate(true); + } + "a" => { + open_options.create(true).append(true); + } + "a+" => { + open_options.read(true).create(true).append(true); + } + "x" => { + open_options.create_new(true).write(true); + } + "x+" => { + open_options.create_new(true).read(true).write(true); + } + &_ => { + panic!("Unknown file open mode."); + } + } + + match mode { + "r" => { + state.check_read(&filename_)?; + } + "w" | "a" | "x" => { + state.check_write(&filename_)?; + } + &_ => { + state.check_read(&filename_)?; + state.check_write(&filename_)?; + } + } + + let op = open_options.open(filename).map_err(ErrBox::from).and_then( + move |fs_file| { + let resource = resources::add_fs_file(fs_file); + let builder = &mut FlatBufferBuilder::new(); + let inner = + msg::OpenRes::create(builder, &msg::OpenResArgs { rid: resource.rid }); + Ok(serialize_response( + cmd_id, + builder, + msg::BaseArgs { + inner: Some(inner.as_union_value()), + inner_type: msg::Any::OpenRes, + ..Default::default() + }, + )) + }, + ); + if base.sync() { + let buf = op.wait()?; + Ok(Op::Sync(buf)) + } else { + Ok(Op::Async(Box::new(op))) + } +} + +pub fn op_close( + _state: &ThreadSafeState, + base: &msg::Base<'_>, + data: Option<PinnedBuf>, +) -> CliOpResult { + assert!(data.is_none()); + let inner = base.inner_as_close().unwrap(); + let rid = inner.rid(); + match resources::lookup(rid) { + None => Err(deno_error::bad_resource()), + Some(resource) => { + resource.close(); + ok_buf(empty_buf()) + } + } +} + +pub fn op_read( + _state: &ThreadSafeState, + base: &msg::Base<'_>, + data: Option<PinnedBuf>, +) -> CliOpResult { + let cmd_id = base.cmd_id(); + let inner = base.inner_as_read().unwrap(); + let rid = inner.rid(); + + match resources::lookup(rid) { + None => Err(deno_error::bad_resource()), + Some(resource) => { + let op = tokio::io::read(resource, data.unwrap()) + .map_err(ErrBox::from) + .and_then(move |(_resource, _buf, nread)| { + let builder = &mut FlatBufferBuilder::new(); + let inner = msg::ReadRes::create( + builder, + &msg::ReadResArgs { + nread: nread as u32, + eof: nread == 0, + }, + ); + Ok(serialize_response( + cmd_id, + builder, + msg::BaseArgs { + inner: Some(inner.as_union_value()), + inner_type: msg::Any::ReadRes, + ..Default::default() + }, + )) + }); + if base.sync() { + let buf = op.wait()?; + Ok(Op::Sync(buf)) + } else { + Ok(Op::Async(Box::new(op))) + } + } + } +} + +pub fn op_write( + _state: &ThreadSafeState, + base: &msg::Base<'_>, + data: Option<PinnedBuf>, +) -> CliOpResult { + let cmd_id = base.cmd_id(); + let inner = base.inner_as_write().unwrap(); + let rid = inner.rid(); + + match resources::lookup(rid) { + None => Err(deno_error::bad_resource()), + Some(resource) => { + let op = tokio_write::write(resource, data.unwrap()) + .map_err(ErrBox::from) + .and_then(move |(_resource, _buf, nwritten)| { + let builder = &mut FlatBufferBuilder::new(); + let inner = msg::WriteRes::create( + builder, + &msg::WriteResArgs { + nbyte: nwritten as u32, + }, + ); + Ok(serialize_response( + cmd_id, + builder, + msg::BaseArgs { + inner: Some(inner.as_union_value()), + inner_type: msg::Any::WriteRes, + ..Default::default() + }, + )) + }); + if base.sync() { + let buf = op.wait()?; + Ok(Op::Sync(buf)) + } else { + Ok(Op::Async(Box::new(op))) + } + } + } +} + +pub fn op_seek( + _state: &ThreadSafeState, + base: &msg::Base<'_>, + data: Option<PinnedBuf>, +) -> CliOpResult { + assert!(data.is_none()); + let inner = base.inner_as_seek().unwrap(); + let rid = inner.rid(); + let offset = inner.offset(); + let whence = inner.whence(); + + match resources::lookup(rid) { + None => Err(deno_error::bad_resource()), + Some(resource) => { + let op = resources::seek(resource, offset, whence) + .and_then(move |_| Ok(empty_buf())); + if base.sync() { + let buf = op.wait()?; + Ok(Op::Sync(buf)) + } else { + Ok(Op::Async(Box::new(op))) + } + } + } +} |