summaryrefslogtreecommitdiff
path: root/src/resources.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/resources.rs')
-rw-r--r--src/resources.rs61
1 files changed, 60 insertions, 1 deletions
diff --git a/src/resources.rs b/src/resources.rs
index 6a15e378c..2d617265e 100644
--- a/src/resources.rs
+++ b/src/resources.rs
@@ -30,7 +30,7 @@ use futures::Stream;
use hyper;
use std;
use std::collections::HashMap;
-use std::io::{Error, Read, Write};
+use std::io::{Error, Read, Seek, SeekFrom, Write};
use std::net::{Shutdown, SocketAddr};
use std::process::ExitStatus;
use std::sync::atomic::AtomicUsize;
@@ -565,3 +565,62 @@ pub fn eager_accept(resource: Resource) -> EagerAccept {
},
}
}
+
+// TODO(kevinkassimo): revamp this after the following lands:
+// https://github.com/tokio-rs/tokio/pull/785
+pub fn seek(
+ resource: Resource,
+ offset: i32,
+ whence: u32,
+) -> Box<dyn Future<Item = (), Error = DenoError> + Send> {
+ let mut table = RESOURCE_TABLE.lock().unwrap();
+ // We take ownership of File here.
+ // It is put back below while still holding the lock.
+ let maybe_repr = table.remove(&resource.rid);
+ match maybe_repr {
+ None => panic!("bad rid"),
+ Some(Repr::FsFile(f)) => {
+ let seek_from = match whence {
+ 0 => SeekFrom::Start(offset as u64),
+ 1 => SeekFrom::Current(offset as i64),
+ 2 => SeekFrom::End(offset as i64),
+ _ => {
+ return Box::new(futures::future::err(errors::new(
+ errors::ErrorKind::InvalidSeekMode,
+ format!("Invalid seek mode: {}", whence),
+ )));
+ }
+ };
+ // Trait Clone not implemented on tokio::fs::File,
+ // so convert to std File first.
+ let std_file = f.into_std();
+ // Create a copy and immediately put back.
+ // We don't want to block other resource ops.
+ // try_clone() would yield a copy containing the same
+ // underlying fd, so operations on the copy would also
+ // affect the one in resource table, and we don't need
+ // to write back.
+ let maybe_std_file_copy = std_file.try_clone();
+ // Insert the entry back with the same rid.
+ table.insert(
+ resource.rid,
+ Repr::FsFile(tokio_fs::File::from_std(std_file)),
+ );
+ if maybe_std_file_copy.is_err() {
+ return Box::new(futures::future::err(DenoError::from(
+ maybe_std_file_copy.unwrap_err(),
+ )));
+ }
+ let mut std_file_copy = maybe_std_file_copy.unwrap();
+ return Box::new(futures::future::lazy(move || {
+ let result = std_file_copy
+ .seek(seek_from)
+ .map(|_| {
+ return ();
+ }).map_err(DenoError::from);
+ futures::future::result(result)
+ }));
+ }
+ _ => panic!("cannot seek"),
+ }
+}