summaryrefslogtreecommitdiffstats
path: root/third_party/rust/tokio-fs/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/tokio-fs/src
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/tokio-fs/src')
-rw-r--r--third_party/rust/tokio-fs/src/create_dir.rs46
-rw-r--r--third_party/rust/tokio-fs/src/create_dir_all.rs47
-rw-r--r--third_party/rust/tokio-fs/src/file/create.rs37
-rw-r--r--third_party/rust/tokio-fs/src/file/metadata.rs39
-rw-r--r--third_party/rust/tokio-fs/src/file/mod.rs243
-rw-r--r--third_party/rust/tokio-fs/src/file/open.rs38
-rw-r--r--third_party/rust/tokio-fs/src/file/open_options.rs103
-rw-r--r--third_party/rust/tokio-fs/src/file/seek.rs37
-rw-r--r--third_party/rust/tokio-fs/src/hard_link.rs54
-rw-r--r--third_party/rust/tokio-fs/src/lib.rs104
-rw-r--r--third_party/rust/tokio-fs/src/metadata.rs45
-rw-r--r--third_party/rust/tokio-fs/src/os/mod.rs6
-rw-r--r--third_party/rust/tokio-fs/src/os/unix.rs55
-rw-r--r--third_party/rust/tokio-fs/src/os/windows/mod.rs7
-rw-r--r--third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs54
-rw-r--r--third_party/rust/tokio-fs/src/os/windows/symlink_file.rs54
-rw-r--r--third_party/rust/tokio-fs/src/read_dir.rs247
-rw-r--r--third_party/rust/tokio-fs/src/read_link.rs46
-rw-r--r--third_party/rust/tokio-fs/src/remove_dir.rs46
-rw-r--r--third_party/rust/tokio-fs/src/remove_file.rs50
-rw-r--r--third_party/rust/tokio-fs/src/rename.rs54
-rw-r--r--third_party/rust/tokio-fs/src/set_permissions.rs48
-rw-r--r--third_party/rust/tokio-fs/src/stderr.rs45
-rw-r--r--third_party/rust/tokio-fs/src/stdin.rs38
-rw-r--r--third_party/rust/tokio-fs/src/stdout.rs44
-rw-r--r--third_party/rust/tokio-fs/src/symlink_metadata.rs49
26 files changed, 1636 insertions, 0 deletions
diff --git a/third_party/rust/tokio-fs/src/create_dir.rs b/third_party/rust/tokio-fs/src/create_dir.rs
new file mode 100644
index 0000000000..a174a5d97f
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/create_dir.rs
@@ -0,0 +1,46 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Creates a new, empty directory at the provided path
+///
+/// This is an async version of [`std::fs::create_dir`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.create_dir.html
+pub fn create_dir<P: AsRef<Path>>(path: P) -> CreateDirFuture<P> {
+ CreateDirFuture::new(path)
+}
+
+/// Future returned by `create_dir`.
+#[derive(Debug)]
+pub struct CreateDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+}
+
+impl<P> CreateDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P) -> CreateDirFuture<P> {
+ CreateDirFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for CreateDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::create_dir(&self.path) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/create_dir_all.rs b/third_party/rust/tokio-fs/src/create_dir_all.rs
new file mode 100644
index 0000000000..3e32480673
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/create_dir_all.rs
@@ -0,0 +1,47 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Recursively create a directory and all of its parent components if they
+/// are missing.
+///
+/// This is an async version of [`std::fs::create_dir_all`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.create_dir_all.html
+pub fn create_dir_all<P: AsRef<Path>>(path: P) -> CreateDirAllFuture<P> {
+ CreateDirAllFuture::new(path)
+}
+
+/// Future returned by `create_dir_all`.
+#[derive(Debug)]
+pub struct CreateDirAllFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+}
+
+impl<P> CreateDirAllFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P) -> CreateDirAllFuture<P> {
+ CreateDirAllFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for CreateDirAllFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::create_dir_all(&self.path) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/create.rs b/third_party/rust/tokio-fs/src/file/create.rs
new file mode 100644
index 0000000000..4027418563
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/create.rs
@@ -0,0 +1,37 @@
+use super::File;
+
+use futures::{Future, Poll};
+
+use std::fs::File as StdFile;
+use std::io;
+use std::path::Path;
+
+/// Future returned by `File::create` and resolves to a `File` instance.
+#[derive(Debug)]
+pub struct CreateFuture<P> {
+ path: P,
+}
+
+impl<P> CreateFuture<P>
+where P: AsRef<Path> + Send + 'static,
+{
+ pub(crate) fn new(path: P) -> Self {
+ CreateFuture { path }
+ }
+}
+
+impl<P> Future for CreateFuture<P>
+where P: AsRef<Path> + Send + 'static,
+{
+ type Item = File;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ let std = try_ready!(::blocking_io(|| {
+ StdFile::create(&self.path)
+ }));
+
+ let file = File::from_std(std);
+ Ok(file.into())
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/metadata.rs b/third_party/rust/tokio-fs/src/file/metadata.rs
new file mode 100644
index 0000000000..b55ca103c1
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/metadata.rs
@@ -0,0 +1,39 @@
+use super::File;
+
+use futures::{Future, Poll};
+
+use std::fs::File as StdFile;
+use std::fs::Metadata;
+use std::io;
+
+const POLL_AFTER_RESOLVE: &str = "Cannot poll MetadataFuture after it resolves";
+
+/// Future returned by `File::metadata` and resolves to a `(Metadata, File)` instance.
+#[derive(Debug)]
+pub struct MetadataFuture {
+ file: Option<File>,
+}
+
+impl MetadataFuture {
+ pub(crate) fn new(file: File) -> Self {
+ MetadataFuture { file: Some(file) }
+ }
+
+ fn std(&mut self) -> &mut StdFile {
+ self.file.as_mut().expect(POLL_AFTER_RESOLVE).std()
+ }
+}
+
+impl Future for MetadataFuture {
+ type Item = (File, Metadata);
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ let metadata = try_ready!(::blocking_io(|| {
+ StdFile::metadata(self.std())
+ }));
+
+ let file = self.file.take().expect(POLL_AFTER_RESOLVE);
+ Ok((file, metadata).into())
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/mod.rs b/third_party/rust/tokio-fs/src/file/mod.rs
new file mode 100644
index 0000000000..c3ae431121
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/mod.rs
@@ -0,0 +1,243 @@
+//! Types for working with [`File`].
+//!
+//! [`File`]: file/struct.File.html
+
+mod create;
+mod metadata;
+mod open;
+mod open_options;
+mod seek;
+
+pub use self::create::CreateFuture;
+pub use self::metadata::MetadataFuture;
+pub use self::open::OpenFuture;
+pub use self::open_options::OpenOptions;
+pub use self::seek::SeekFuture;
+
+use tokio_io::{AsyncRead, AsyncWrite};
+
+use futures::Poll;
+
+use std::fs::{File as StdFile, Metadata, Permissions};
+use std::io::{self, Read, Write, Seek};
+use std::path::Path;
+
+/// A reference to an open file on the filesystem.
+///
+/// This is a specialized version of [`std::fs::File`][std] for usage from the
+/// Tokio runtime.
+///
+/// An instance of a `File` can be read and/or written depending on what options
+/// it was opened with. Files also implement Seek to alter the logical cursor
+/// that the file contains internally.
+///
+/// Files are automatically closed when they go out of scope.
+///
+/// [std]: https://doc.rust-lang.org/std/fs/struct.File.html
+#[derive(Debug)]
+pub struct File {
+ std: Option<StdFile>,
+}
+
+impl File {
+ /// Attempts to open a file in read-only mode.
+ ///
+ /// See [`OpenOptions`] for more details.
+ ///
+ /// [`OpenOptions`]: struct.OpenOptions.html
+ ///
+ /// # Errors
+ ///
+ /// `OpenFuture` results in an error if called from outside of the Tokio
+ /// runtime or if the underlying [`open`] call results in an error.
+ ///
+ /// [`open`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.open
+ pub fn open<P>(path: P) -> OpenFuture<P>
+ where P: AsRef<Path> + Send + 'static,
+ {
+ OpenOptions::new().read(true).open(path)
+ }
+
+ /// Opens a file in write-only mode.
+ ///
+ /// This function will create a file if it does not exist, and will truncate
+ /// it if it does.
+ ///
+ /// See [`OpenOptions`] for more details.
+ ///
+ /// [`OpenOptions`]: struct.OpenOptions.html
+ ///
+ /// # Errors
+ ///
+ /// `CreateFuture` results in an error if called from outside of the Tokio
+ /// runtime or if the underlying [`create`] call results in an error.
+ ///
+ /// [`create`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.create
+ pub fn create<P>(path: P) -> CreateFuture<P>
+ where P: AsRef<Path> + Send + 'static,
+ {
+ CreateFuture::new(path)
+ }
+
+ /// Convert a [`std::fs::File`][std] to a `tokio_fs::File`.
+ ///
+ /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html
+ pub(crate) fn from_std(std: StdFile) -> File {
+ File { std: Some(std) }
+ }
+
+ /// Seek to an offset, in bytes, in a stream.
+ ///
+ /// A seek beyond the end of a stream is allowed, but implementation
+ /// defined.
+ ///
+ /// If the seek operation completed successfully, this method returns the
+ /// new position from the start of the stream. That position can be used
+ /// later with `SeekFrom::Start`.
+ ///
+ /// # Errors
+ ///
+ /// Seeking to a negative offset is considered an error.
+ pub fn poll_seek(&mut self, pos: io::SeekFrom) -> Poll<u64, io::Error> {
+ ::blocking_io(|| self.std().seek(pos))
+ }
+
+ /// Seek to an offset, in bytes, in a stream.
+ ///
+ /// Similar to `poll_seek`, but returning a `Future`.
+ ///
+ /// This method consumes the `File` and returns it back when the future
+ /// completes.
+ pub fn seek(self, pos: io::SeekFrom) -> SeekFuture {
+ SeekFuture::new(self, pos)
+ }
+
+ /// Attempts to sync all OS-internal metadata to disk.
+ ///
+ /// This function will attempt to ensure that all in-core data reaches the
+ /// filesystem before returning.
+ pub fn poll_sync_all(&mut self) -> Poll<(), io::Error> {
+ ::blocking_io(|| self.std().sync_all())
+ }
+
+ /// This function is similar to `poll_sync_all`, except that it may not
+ /// synchronize file metadata to the filesystem.
+ ///
+ /// This is intended for use cases that must synchronize content, but don't
+ /// need the metadata on disk. The goal of this method is to reduce disk
+ /// operations.
+ ///
+ /// Note that some platforms may simply implement this in terms of `poll_sync_all`.
+ pub fn poll_sync_data(&mut self) -> Poll<(), io::Error> {
+ ::blocking_io(|| self.std().sync_data())
+ }
+
+ /// Truncates or extends the underlying file, updating the size of this file to become size.
+ ///
+ /// If the size is less than the current file's size, then the file will be
+ /// shrunk. If it is greater than the current file's size, then the file
+ /// will be extended to size and have all of the intermediate data filled in
+ /// with 0s.
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if the file is not opened for
+ /// writing.
+ pub fn poll_set_len(&mut self, size: u64) -> Poll<(), io::Error> {
+ ::blocking_io(|| self.std().set_len(size))
+ }
+
+ /// Queries metadata about the underlying file.
+ pub fn metadata(self) -> MetadataFuture {
+ MetadataFuture::new(self)
+ }
+
+ /// Queries metadata about the underlying file.
+ pub fn poll_metadata(&mut self) -> Poll<Metadata, io::Error> {
+ ::blocking_io(|| self.std().metadata())
+ }
+
+ /// Create a new `File` instance that shares the same underlying file handle
+ /// as the existing `File` instance. Reads, writes, and seeks will affect both
+ /// File instances simultaneously.
+ pub fn poll_try_clone(&mut self) -> Poll<File, io::Error> {
+ ::blocking_io(|| {
+ let std = self.std().try_clone()?;
+ Ok(File::from_std(std))
+ })
+ }
+
+ /// Changes the permissions on the underlying file.
+ ///
+ /// # Platform-specific behavior
+ ///
+ /// This function currently corresponds to the `fchmod` function on Unix and
+ /// the `SetFileInformationByHandle` function on Windows. Note that, this
+ /// [may change in the future][changes].
+ ///
+ /// [changes]: https://doc.rust-lang.org/std/io/index.html#platform-specific-behavior
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if the user lacks permission change
+ /// attributes on the underlying file. It may also return an error in other
+ /// os-specific unspecified cases.
+ pub fn poll_set_permissions(&mut self, perm: Permissions) -> Poll<(), io::Error> {
+ ::blocking_io(|| self.std().set_permissions(perm))
+ }
+
+ /// Destructures the `tokio_fs::File` into a [`std::fs::File`][std].
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if `shutdown` has been called.
+ ///
+ /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html
+ pub fn into_std(mut self) -> StdFile {
+ self.std.take().expect("`File` instance already shutdown")
+ }
+
+ fn std(&mut self) -> &mut StdFile {
+ self.std.as_mut().expect("`File` instance already shutdown")
+ }
+}
+
+impl Read for File {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ ::would_block(|| self.std().read(buf))
+ }
+}
+
+impl AsyncRead for File {
+ unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
+ false
+ }
+}
+
+impl Write for File {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ ::would_block(|| self.std().write(buf))
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ ::would_block(|| self.std().flush())
+ }
+}
+
+impl AsyncWrite for File {
+ fn shutdown(&mut self) -> Poll<(), io::Error> {
+ ::blocking_io(|| {
+ self.std = None;
+ Ok(())
+ })
+ }
+}
+
+impl Drop for File {
+ fn drop(&mut self) {
+ if let Some(_std) = self.std.take() {
+ // This is probably fine as closing a file *shouldn't* be a blocking
+ // operation. That said, ideally `shutdown` is called first.
+ }
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/open.rs b/third_party/rust/tokio-fs/src/file/open.rs
new file mode 100644
index 0000000000..197ec237af
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/open.rs
@@ -0,0 +1,38 @@
+use super::File;
+
+use futures::{Future, Poll};
+
+use std::fs::OpenOptions as StdOpenOptions;
+use std::io;
+use std::path::Path;
+
+/// Future returned by `File::open` and resolves to a `File` instance.
+#[derive(Debug)]
+pub struct OpenFuture<P> {
+ options: StdOpenOptions,
+ path: P,
+}
+
+impl<P> OpenFuture<P>
+where P: AsRef<Path> + Send + 'static,
+{
+ pub(crate) fn new(options: StdOpenOptions, path: P) -> Self {
+ OpenFuture { options, path }
+ }
+}
+
+impl<P> Future for OpenFuture<P>
+where P: AsRef<Path> + Send + 'static,
+{
+ type Item = File;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ let std = try_ready!(::blocking_io(|| {
+ self.options.open(&self.path)
+ }));
+
+ let file = File::from_std(std);
+ Ok(file.into())
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/open_options.rs b/third_party/rust/tokio-fs/src/file/open_options.rs
new file mode 100644
index 0000000000..99cc71c5b0
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/open_options.rs
@@ -0,0 +1,103 @@
+use super::OpenFuture;
+
+use std::convert::From;
+use std::fs::OpenOptions as StdOpenOptions;
+use std::path::Path;
+
+/// Options and flags which can be used to configure how a file is opened.
+///
+/// This is a specialized version of [`std::fs::OpenOptions`] for usage from
+/// the Tokio runtime.
+///
+/// `From<std::fs::OpenOptions>` is implemented for more advanced configuration
+/// than the methods provided here.
+///
+/// [`std::fs::OpenOptions`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html
+#[derive(Clone, Debug)]
+pub struct OpenOptions(StdOpenOptions);
+
+impl OpenOptions {
+ /// Creates a blank new set of options ready for configuration.
+ ///
+ /// All options are initially set to `false`.
+ ///
+ /// # Examples
+ ///
+ /// ```ignore
+ /// use tokio::fs::OpenOptions;
+ ///
+ /// let mut options = OpenOptions::new();
+ /// let future = options.read(true).open("foo.txt");
+ /// ```
+ pub fn new() -> OpenOptions {
+ OpenOptions(StdOpenOptions::new())
+ }
+
+ /// See the underlying [`read`] call for details.
+ ///
+ /// [`read`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.read
+ pub fn read(&mut self, read: bool) -> &mut OpenOptions {
+ self.0.read(read);
+ self
+ }
+
+ /// See the underlying [`write`] call for details.
+ ///
+ /// [`write`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.write
+ pub fn write(&mut self, write: bool) -> &mut OpenOptions {
+ self.0.write(write);
+ self
+ }
+
+ /// See the underlying [`append`] call for details.
+ ///
+ /// [`append`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.append
+ pub fn append(&mut self, append: bool) -> &mut OpenOptions {
+ self.0.append(append);
+ self
+ }
+
+ /// See the underlying [`truncate`] call for details.
+ ///
+ /// [`truncate`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.truncate
+ pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
+ self.0.truncate(truncate);
+ self
+ }
+
+ /// See the underlying [`create`] call for details.
+ ///
+ /// [`create`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create
+ pub fn create(&mut self, create: bool) -> &mut OpenOptions {
+ self.0.create(create);
+ self
+ }
+
+ /// See the underlying [`create_new`] call for details.
+ ///
+ /// [`create_new`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create_new
+ pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions {
+ self.0.create_new(create_new);
+ self
+ }
+
+ /// Opens a file at `path` with the options specified by `self`.
+ ///
+ /// # Errors
+ ///
+ /// `OpenOptionsFuture` results in an error if called from outside of the
+ /// Tokio runtime or if the underlying [`open`] call results in an error.
+ ///
+ /// [`open`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open
+ pub fn open<P>(&self, path: P) -> OpenFuture<P>
+ where P: AsRef<Path> + Send + 'static
+ {
+ OpenFuture::new(self.0.clone(), path)
+ }
+}
+
+impl From<StdOpenOptions> for OpenOptions {
+ fn from(options: StdOpenOptions) -> OpenOptions {
+ OpenOptions(options)
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/seek.rs b/third_party/rust/tokio-fs/src/file/seek.rs
new file mode 100644
index 0000000000..0765d3db90
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/seek.rs
@@ -0,0 +1,37 @@
+use super::File;
+
+use futures::{Future, Poll};
+
+use std::io;
+
+/// Future returned by `File::seek`.
+#[derive(Debug)]
+pub struct SeekFuture {
+ inner: Option<File>,
+ pos: io::SeekFrom,
+}
+
+impl SeekFuture {
+ pub(crate) fn new(file: File, pos: io::SeekFrom) -> Self {
+ Self {
+ pos,
+ inner: Some(file),
+ }
+ }
+}
+
+impl Future for SeekFuture {
+ type Item = (File, u64);
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ let pos = try_ready!(
+ self.inner
+ .as_mut()
+ .expect("Cannot poll `SeekFuture` after it resolves")
+ .poll_seek(self.pos)
+ );
+ let inner = self.inner.take().unwrap();
+ Ok((inner, pos).into())
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/hard_link.rs b/third_party/rust/tokio-fs/src/hard_link.rs
new file mode 100644
index 0000000000..e8ea511520
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/hard_link.rs
@@ -0,0 +1,54 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Creates a new hard link on the filesystem.
+///
+/// The `dst` path will be a link pointing to the `src` path. Note that systems
+/// often require these two paths to both be located on the same filesystem.
+///
+/// This is an async version of [`std::fs::hard_link`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.hard_link.html
+pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> HardLinkFuture<P, Q> {
+ HardLinkFuture::new(src, dst)
+}
+
+/// Future returned by `hard_link`.
+#[derive(Debug)]
+pub struct HardLinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ src: P,
+ dst: Q,
+}
+
+impl<P, Q> HardLinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ fn new(src: P, dst: Q) -> HardLinkFuture<P, Q> {
+ HardLinkFuture {
+ src: src,
+ dst: dst,
+ }
+ }
+}
+
+impl<P, Q> Future for HardLinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::hard_link(&self.src, &self.dst) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/lib.rs b/third_party/rust/tokio-fs/src/lib.rs
new file mode 100644
index 0000000000..2beec8c0c6
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/lib.rs
@@ -0,0 +1,104 @@
+//! Asynchronous file and standard stream adaptation.
+//!
+//! This module contains utility methods and adapter types for input/output to
+//! files or standard streams (`Stdin`, `Stdout`, `Stderr`), and
+//! filesystem manipulation, for use within (and only within) a Tokio runtime.
+//!
+//! Tasks run by *worker* threads should not block, as this could delay
+//! servicing reactor events. Portable filesystem operations are blocking,
+//! however. This module offers adapters which use a [`blocking`] annotation
+//! to inform the runtime that a blocking operation is required. When
+//! necessary, this allows the runtime to convert the current thread from a
+//! *worker* to a *backup* thread, where blocking is acceptable.
+//!
+//! ## Usage
+//!
+//! Where possible, users should prefer the provided asynchronous-specific
+//! traits such as [`AsyncRead`], or methods returning a `Future` or `Poll`
+//! type. Adaptions also extend to traits like `std::io::Read` where methods
+//! return `std::io::Result`. Be warned that these adapted methods may return
+//! `std::io::ErrorKind::WouldBlock` if a *worker* thread can not be converted
+//! to a *backup* thread immediately. See [tokio-threadpool] for more details
+//! of the threading model and [`blocking`].
+//!
+//! [`blocking`]: https://docs.rs/tokio-threadpool/0.1/tokio_threadpool/fn.blocking.html
+//! [`AsyncRead`]: https://docs.rs/tokio-io/0.1/tokio_io/trait.AsyncRead.html
+//! [tokio-threadpool]: https://docs.rs/tokio-threadpool/0.1/tokio_threadpool
+
+#![deny(missing_docs, missing_debug_implementations, warnings)]
+#![doc(html_root_url = "https://docs.rs/tokio-fs/0.1.3")]
+
+#[macro_use]
+extern crate futures;
+extern crate tokio_io;
+extern crate tokio_threadpool;
+
+mod create_dir;
+mod create_dir_all;
+pub mod file;
+mod hard_link;
+mod metadata;
+pub mod os;
+mod read_dir;
+mod read_link;
+mod remove_dir;
+mod remove_file;
+mod rename;
+mod set_permissions;
+mod stdin;
+mod stdout;
+mod stderr;
+mod symlink_metadata;
+
+pub use create_dir::{create_dir, CreateDirFuture};
+pub use create_dir_all::{create_dir_all, CreateDirAllFuture};
+pub use file::File;
+pub use file::OpenOptions;
+pub use hard_link::{hard_link, HardLinkFuture};
+pub use metadata::{metadata, MetadataFuture};
+pub use read_dir::{read_dir, ReadDirFuture, ReadDir, DirEntry};
+pub use read_link::{read_link, ReadLinkFuture};
+pub use remove_dir::{remove_dir, RemoveDirFuture};
+pub use remove_file::{remove_file, RemoveFileFuture};
+pub use rename::{rename, RenameFuture};
+pub use set_permissions::{set_permissions, SetPermissionsFuture};
+pub use stdin::{stdin, Stdin};
+pub use stdout::{stdout, Stdout};
+pub use stderr::{stderr, Stderr};
+pub use symlink_metadata::{symlink_metadata, SymlinkMetadataFuture};
+
+use futures::Poll;
+use futures::Async::*;
+
+use std::io;
+use std::io::ErrorKind::{Other, WouldBlock};
+
+fn blocking_io<F, T>(f: F) -> Poll<T, io::Error>
+where F: FnOnce() -> io::Result<T>,
+{
+ match tokio_threadpool::blocking(f) {
+ Ok(Ready(Ok(v))) => Ok(v.into()),
+ Ok(Ready(Err(err))) => Err(err),
+ Ok(NotReady) => Ok(NotReady),
+ Err(_) => Err(blocking_err()),
+ }
+}
+
+fn would_block<F, T>(f: F) -> io::Result<T>
+where F: FnOnce() -> io::Result<T>,
+{
+ match tokio_threadpool::blocking(f) {
+ Ok(Ready(Ok(v))) => Ok(v),
+ Ok(Ready(Err(err))) => {
+ debug_assert_ne!(err.kind(), WouldBlock);
+ Err(err)
+ }
+ Ok(NotReady) => Err(WouldBlock.into()),
+ Err(_) => Err(blocking_err()),
+ }
+}
+
+fn blocking_err() -> io::Error {
+ io::Error::new(Other, "`blocking` annotated I/O must be called \
+ from the context of the Tokio runtime.")
+}
diff --git a/third_party/rust/tokio-fs/src/metadata.rs b/third_party/rust/tokio-fs/src/metadata.rs
new file mode 100644
index 0000000000..200d58e080
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/metadata.rs
@@ -0,0 +1,45 @@
+use super::blocking_io;
+
+use futures::{Future, Poll};
+
+use std::fs::{self, Metadata};
+use std::io;
+use std::path::Path;
+
+/// Queries the file system metadata for a path.
+pub fn metadata<P>(path: P) -> MetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ MetadataFuture::new(path)
+}
+
+/// Future returned by `metadata`.
+#[derive(Debug)]
+pub struct MetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ path: P,
+}
+
+impl<P> MetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ pub(crate) fn new(path: P) -> Self {
+ Self { path }
+ }
+}
+
+impl<P> Future for MetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ type Item = Metadata;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ blocking_io(|| fs::metadata(&self.path))
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/os/mod.rs b/third_party/rust/tokio-fs/src/os/mod.rs
new file mode 100644
index 0000000000..ae57c48476
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/os/mod.rs
@@ -0,0 +1,6 @@
+//! OS-specific functionality.
+
+#[cfg(unix)]
+pub mod unix;
+#[cfg(windows)]
+pub mod windows;
diff --git a/third_party/rust/tokio-fs/src/os/unix.rs b/third_party/rust/tokio-fs/src/os/unix.rs
new file mode 100644
index 0000000000..5f8eedeba3
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/os/unix.rs
@@ -0,0 +1,55 @@
+//! Unix-specific extensions to primitives in the `tokio_fs` module.
+
+use std::io;
+use std::path::Path;
+use std::os::unix::fs;
+
+use futures::{Future, Poll};
+
+/// Creates a new symbolic link on the filesystem.
+///
+/// The `dst` path will be a symbolic link pointing to the `src` path.
+///
+/// This is an async version of [`std::os::unix::fs::symlink`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/os/unix/fs/fn.symlink.html
+pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> SymlinkFuture<P, Q> {
+ SymlinkFuture::new(src, dst)
+}
+
+/// Future returned by `symlink`.
+#[derive(Debug)]
+pub struct SymlinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ src: P,
+ dst: Q,
+}
+
+impl<P, Q> SymlinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ fn new(src: P, dst: Q) -> SymlinkFuture<P, Q> {
+ SymlinkFuture {
+ src: src,
+ dst: dst,
+ }
+ }
+}
+
+impl<P, Q> Future for SymlinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::symlink(&self.src, &self.dst) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/os/windows/mod.rs b/third_party/rust/tokio-fs/src/os/windows/mod.rs
new file mode 100644
index 0000000000..eaeed043eb
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/os/windows/mod.rs
@@ -0,0 +1,7 @@
+//! Windows-specific extensions for the primitives in the `tokio_fs` module.
+
+mod symlink_dir;
+mod symlink_file;
+
+pub use self::symlink_dir::{symlink_dir, SymlinkDirFuture};
+pub use self::symlink_file::{symlink_file, SymlinkFileFuture};
diff --git a/third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs b/third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs
new file mode 100644
index 0000000000..9806ff3a3f
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs
@@ -0,0 +1,54 @@
+use std::io;
+use std::path::Path;
+use std::os::windows::fs;
+
+use futures::{Future, Poll};
+
+/// Creates a new directory symlink on the filesystem.
+///
+/// The `dst` path will be a directory symbolic link pointing to the `src`
+/// path.
+///
+/// This is an async version of [`std::os::windows::fs::symlink_dir`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_dir.html
+pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> SymlinkDirFuture<P, Q> {
+ SymlinkDirFuture::new(src, dst)
+}
+
+/// Future returned by `symlink_dir`.
+#[derive(Debug)]
+pub struct SymlinkDirFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ src: P,
+ dst: Q,
+}
+
+impl<P, Q> SymlinkDirFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ fn new(src: P, dst: Q) -> SymlinkDirFuture<P, Q> {
+ SymlinkDirFuture {
+ src: src,
+ dst: dst,
+ }
+ }
+}
+
+impl<P, Q> Future for SymlinkDirFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::symlink_dir(&self.src, &self.dst) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/os/windows/symlink_file.rs b/third_party/rust/tokio-fs/src/os/windows/symlink_file.rs
new file mode 100644
index 0000000000..583b615874
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/os/windows/symlink_file.rs
@@ -0,0 +1,54 @@
+use std::io;
+use std::path::Path;
+use std::os::windows::fs;
+
+use futures::{Future, Poll};
+
+/// Creates a new file symbolic link on the filesystem.
+///
+/// The `dst` path will be a file symbolic link pointing to the `src`
+/// path.
+///
+/// This is an async version of [`std::os::windows::fs::symlink_file`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_file.html
+pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> SymlinkFileFuture<P, Q> {
+ SymlinkFileFuture::new(src, dst)
+}
+
+/// Future returned by `symlink_file`.
+#[derive(Debug)]
+pub struct SymlinkFileFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ src: P,
+ dst: Q,
+}
+
+impl<P, Q> SymlinkFileFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ fn new(src: P, dst: Q) -> SymlinkFileFuture<P, Q> {
+ SymlinkFileFuture {
+ src: src,
+ dst: dst,
+ }
+ }
+}
+
+impl<P, Q> Future for SymlinkFileFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::symlink_file(&self.src, &self.dst) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/read_dir.rs b/third_party/rust/tokio-fs/src/read_dir.rs
new file mode 100644
index 0000000000..3818c7102b
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/read_dir.rs
@@ -0,0 +1,247 @@
+use std::ffi::OsString;
+use std::fs::{self, DirEntry as StdDirEntry, ReadDir as StdReadDir, FileType, Metadata};
+use std::io;
+#[cfg(unix)]
+use std::os::unix::fs::DirEntryExt;
+use std::path::{Path, PathBuf};
+
+use futures::{Future, Poll, Stream};
+
+/// Returns a stream over the entries within a directory.
+///
+/// This is an async version of [`std::fs::read_dir`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.read_dir.html
+pub fn read_dir<P>(path: P) -> ReadDirFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ ReadDirFuture::new(path)
+}
+
+/// Future returned by `read_dir`.
+#[derive(Debug)]
+pub struct ReadDirFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ path: P,
+}
+
+impl<P> ReadDirFuture<P>
+where
+ P: AsRef<Path> + Send + 'static
+{
+ fn new(path: P) -> ReadDirFuture<P> {
+ ReadDirFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for ReadDirFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ type Item = ReadDir;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, io::Error> {
+ ::blocking_io(|| Ok(ReadDir(fs::read_dir(&self.path)?)))
+ }
+}
+
+/// Stream of the entries in a directory.
+///
+/// This stream is returned from the [`read_dir`] function of this module and
+/// will yield instances of [`DirEntry`]. Through a [`DirEntry`]
+/// information like the entry's path and possibly other metadata can be
+/// learned.
+///
+/// # Errors
+///
+/// This [`Stream`] will return an [`Err`] if there's some sort of intermittent
+/// IO error during iteration.
+///
+/// [`read_dir`]: fn.read_dir.html
+/// [`DirEntry`]: struct.DirEntry.html
+/// [`Stream`]: ../futures/stream/trait.Stream.html
+/// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
+#[derive(Debug)]
+pub struct ReadDir(StdReadDir);
+
+impl Stream for ReadDir {
+ type Item = DirEntry;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
+ ::blocking_io(|| {
+ match self.0.next() {
+ Some(Err(err)) => Err(err),
+ Some(Ok(item)) => Ok(Some(DirEntry(item))),
+ None => Ok(None)
+ }
+ })
+ }
+}
+
+/// Entries returned by the [`ReadDir`] stream.
+///
+/// [`ReadDir`]: struct.ReadDir.html
+///
+/// This is a specialized version of [`std::fs::DirEntry`][std] for usage from the
+/// Tokio runtime.
+///
+/// An instance of `DirEntry` represents an entry inside of a directory on the
+/// filesystem. Each entry can be inspected via methods to learn about the full
+/// path or possibly other metadata through per-platform extension traits.
+///
+/// [std]: https://doc.rust-lang.org/std/fs/struct.DirEntry.html
+#[derive(Debug)]
+pub struct DirEntry(StdDirEntry);
+
+impl DirEntry {
+ /// Destructures the `tokio_fs::DirEntry` into a [`std::fs::DirEntry`][std].
+ ///
+ /// [std]: https://doc.rust-lang.org/std/fs/struct.DirEntry.html
+ pub fn into_std(self) -> StdDirEntry {
+ self.0
+ }
+
+ /// Returns the full path to the file that this entry represents.
+ ///
+ /// The full path is created by joining the original path to `read_dir`
+ /// with the filename of this entry.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # extern crate futures;
+ /// # extern crate tokio;
+ /// # extern crate tokio_fs;
+ /// use futures::{Future, Stream};
+ ///
+ /// fn main() {
+ /// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| {
+ /// println!("{:?}", dir.path());
+ /// Ok(())
+ /// }).map_err(|err| { eprintln!("Error: {:?}", err); () });
+ /// tokio::run(fut);
+ /// }
+ /// ```
+ ///
+ /// This prints output like:
+ ///
+ /// ```text
+ /// "./whatever.txt"
+ /// "./foo.html"
+ /// "./hello_world.rs"
+ /// ```
+ ///
+ /// The exact text, of course, depends on what files you have in `.`.
+ pub fn path(&self) -> PathBuf {
+ self.0.path()
+ }
+
+ /// Returns the bare file name of this directory entry without any other
+ /// leading path component.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # extern crate futures;
+ /// # extern crate tokio;
+ /// # extern crate tokio_fs;
+ /// use futures::{Future, Stream};
+ ///
+ /// fn main() {
+ /// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| {
+ /// // Here, `dir` is a `DirEntry`.
+ /// println!("{:?}", dir.file_name());
+ /// Ok(())
+ /// }).map_err(|err| { eprintln!("Error: {:?}", err); () });
+ /// tokio::run(fut);
+ /// }
+ /// ```
+ pub fn file_name(&self) -> OsString {
+ self.0.file_name()
+ }
+
+ /// Return the metadata for the file that this entry points at.
+ ///
+ /// This function will not traverse symlinks if this entry points at a
+ /// symlink.
+ ///
+ /// # Platform-specific behavior
+ ///
+ /// On Windows this function is cheap to call (no extra system calls
+ /// needed), but on Unix platforms this function is the equivalent of
+ /// calling `symlink_metadata` on the path.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # extern crate futures;
+ /// # extern crate tokio;
+ /// # extern crate tokio_fs;
+ /// use futures::{Future, Stream};
+ /// use futures::future::poll_fn;
+ ///
+ /// fn main() {
+ /// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| {
+ /// // Here, `dir` is a `DirEntry`.
+ /// let path = dir.path();
+ /// poll_fn(move || dir.poll_metadata()).map(move |metadata| {
+ /// println!("{:?}: {:?}", path, metadata.permissions());
+ /// })
+ /// }).map_err(|err| { eprintln!("Error: {:?}", err); () });
+ /// tokio::run(fut);
+ /// }
+ /// ```
+ pub fn poll_metadata(&self) -> Poll<Metadata, io::Error> {
+ ::blocking_io(|| self.0.metadata())
+ }
+
+ /// Return the file type for the file that this entry points at.
+ ///
+ /// This function will not traverse symlinks if this entry points at a
+ /// symlink.
+ ///
+ /// # Platform-specific behavior
+ ///
+ /// On Windows and most Unix platforms this function is free (no extra
+ /// system calls needed), but some Unix platforms may require the equivalent
+ /// call to `symlink_metadata` to learn about the target file type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # extern crate futures;
+ /// # extern crate tokio;
+ /// # extern crate tokio_fs;
+ /// use futures::{Future, Stream};
+ /// use futures::future::poll_fn;
+ ///
+ /// fn main() {
+ /// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| {
+ /// // Here, `dir` is a `DirEntry`.
+ /// let path = dir.path();
+ /// poll_fn(move || dir.poll_file_type()).map(move |file_type| {
+ /// // Now let's show our entry's file type!
+ /// println!("{:?}: {:?}", path, file_type);
+ /// })
+ /// }).map_err(|err| { eprintln!("Error: {:?}", err); () });
+ /// tokio::run(fut);
+ /// }
+ /// ```
+ pub fn poll_file_type(&self) -> Poll<FileType, io::Error> {
+ ::blocking_io(|| self.0.file_type())
+ }
+}
+
+#[cfg(unix)]
+impl DirEntryExt for DirEntry {
+ fn ino(&self) -> u64 {
+ self.0.ino()
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/read_link.rs b/third_party/rust/tokio-fs/src/read_link.rs
new file mode 100644
index 0000000000..5e5bf2a30e
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/read_link.rs
@@ -0,0 +1,46 @@
+use std::fs;
+use std::io;
+use std::path::{Path, PathBuf};
+
+use futures::{Future, Poll};
+
+/// Reads a symbolic link, returning the file that the link points to.
+///
+/// This is an async version of [`std::fs::read_link`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.read_link.html
+pub fn read_link<P: AsRef<Path>>(path: P) -> ReadLinkFuture<P> {
+ ReadLinkFuture::new(path)
+}
+
+/// Future returned by `read_link`.
+#[derive(Debug)]
+pub struct ReadLinkFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+}
+
+impl<P> ReadLinkFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P) -> ReadLinkFuture<P> {
+ ReadLinkFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for ReadLinkFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = PathBuf;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::read_link(&self.path) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/remove_dir.rs b/third_party/rust/tokio-fs/src/remove_dir.rs
new file mode 100644
index 0000000000..5aa73bfb5f
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/remove_dir.rs
@@ -0,0 +1,46 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Removes an existing, empty directory.
+///
+/// This is an async version of [`std::fs::remove_dir`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.remove_dir.html
+pub fn remove_dir<P: AsRef<Path>>(path: P) -> RemoveDirFuture<P> {
+ RemoveDirFuture::new(path)
+}
+
+/// Future returned by `remove_dir`.
+#[derive(Debug)]
+pub struct RemoveDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+}
+
+impl<P> RemoveDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P) -> RemoveDirFuture<P> {
+ RemoveDirFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for RemoveDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::remove_dir(&self.path) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/remove_file.rs b/third_party/rust/tokio-fs/src/remove_file.rs
new file mode 100644
index 0000000000..f617418579
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/remove_file.rs
@@ -0,0 +1,50 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Removes a file from the filesystem.
+///
+/// Note that there is no
+/// guarantee that the file is immediately deleted (e.g. depending on
+/// platform, other open file descriptors may prevent immediate removal).
+///
+/// This is an async version of [`std::fs::remove_file`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.remove_file.html
+pub fn remove_file<P: AsRef<Path>>(path: P) -> RemoveFileFuture<P> {
+ RemoveFileFuture::new(path)
+}
+
+/// Future returned by `remove_file`.
+#[derive(Debug)]
+pub struct RemoveFileFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+}
+
+impl<P> RemoveFileFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P) -> RemoveFileFuture<P> {
+ RemoveFileFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for RemoveFileFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::remove_file(&self.path) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/rename.rs b/third_party/rust/tokio-fs/src/rename.rs
new file mode 100644
index 0000000000..210f53bb5a
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/rename.rs
@@ -0,0 +1,54 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Rename a file or directory to a new name, replacing the original file if
+/// `to` already exists.
+///
+/// This will not work if the new name is on a different mount point.
+///
+/// This is an async version of [`std::fs::rename`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.rename.html
+pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> RenameFuture<P, Q> {
+ RenameFuture::new(from, to)
+}
+
+/// Future returned by `rename`.
+#[derive(Debug)]
+pub struct RenameFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ from: P,
+ to: Q,
+}
+
+impl<P, Q> RenameFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ fn new(from: P, to: Q) -> RenameFuture<P, Q> {
+ RenameFuture {
+ from: from,
+ to: to,
+ }
+ }
+}
+
+impl<P, Q> Future for RenameFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::rename(&self.from, &self.to) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/set_permissions.rs b/third_party/rust/tokio-fs/src/set_permissions.rs
new file mode 100644
index 0000000000..a850448626
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/set_permissions.rs
@@ -0,0 +1,48 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Changes the permissions found on a file or a directory.
+///
+/// This is an async version of [`std::fs::set_permissions`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.set_permissions.html
+pub fn set_permissions<P: AsRef<Path>>(path: P, perm: fs::Permissions) -> SetPermissionsFuture<P> {
+ SetPermissionsFuture::new(path, perm)
+}
+
+/// Future returned by `set_permissions`.
+#[derive(Debug)]
+pub struct SetPermissionsFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+ perm: fs::Permissions,
+}
+
+impl<P> SetPermissionsFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P, perm: fs::Permissions) -> SetPermissionsFuture<P> {
+ SetPermissionsFuture {
+ path: path,
+ perm: perm,
+ }
+ }
+}
+
+impl<P> Future for SetPermissionsFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::set_permissions(&self.path, self.perm.clone()) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/stderr.rs b/third_party/rust/tokio-fs/src/stderr.rs
new file mode 100644
index 0000000000..cf64390757
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/stderr.rs
@@ -0,0 +1,45 @@
+use tokio_io::{AsyncWrite};
+
+use futures::Poll;
+
+use std::io::{self, Write, Stderr as StdStderr};
+
+/// A handle to the standard error stream of a process.
+///
+/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent
+/// writes to `Stderr` must be executed with care.
+///
+/// Created by the [`stderr`] function.
+///
+/// [`stderr`]: fn.stderr.html
+/// [`AsyncWrite`]: trait.AsyncWrite.html
+#[derive(Debug)]
+pub struct Stderr {
+ std: StdStderr,
+}
+
+/// Constructs a new handle to the standard error of the current process.
+///
+/// The returned handle allows writing to standard error from the within the
+/// Tokio runtime.
+pub fn stderr() -> Stderr {
+ let std = io::stderr();
+ Stderr { std }
+}
+
+impl Write for Stderr {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ ::would_block(|| self.std.write(buf))
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ ::would_block(|| self.std.flush())
+ }
+}
+
+impl AsyncWrite for Stderr {
+ fn shutdown(&mut self) -> Poll<(), io::Error> {
+ Ok(().into())
+ }
+}
+
diff --git a/third_party/rust/tokio-fs/src/stdin.rs b/third_party/rust/tokio-fs/src/stdin.rs
new file mode 100644
index 0000000000..f41b8dc84c
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/stdin.rs
@@ -0,0 +1,38 @@
+use tokio_io::{AsyncRead};
+
+use std::io::{self, Read, Stdin as StdStdin};
+
+/// A handle to the standard input stream of a process.
+///
+/// The handle implements the [`AsyncRead`] trait, but beware that concurrent
+/// reads of `Stdin` must be executed with care.
+///
+/// Created by the [`stdin`] function.
+///
+/// [`stdin`]: fn.stdin.html
+/// [`AsyncRead`]: trait.AsyncRead.html
+#[derive(Debug)]
+pub struct Stdin {
+ std: StdStdin,
+}
+
+/// Constructs a new handle to the standard input of the current process.
+///
+/// The returned handle allows reading from standard input from the within the
+/// Tokio runtime.
+pub fn stdin() -> Stdin {
+ let std = io::stdin();
+ Stdin { std }
+}
+
+impl Read for Stdin {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ ::would_block(|| self.std.read(buf))
+ }
+}
+
+impl AsyncRead for Stdin {
+ unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
+ false
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/stdout.rs b/third_party/rust/tokio-fs/src/stdout.rs
new file mode 100644
index 0000000000..1c4cd5ad05
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/stdout.rs
@@ -0,0 +1,44 @@
+use tokio_io::{AsyncWrite};
+
+use futures::Poll;
+
+use std::io::{self, Write, Stdout as StdStdout};
+
+/// A handle to the standard output stream of a process.
+///
+/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent
+/// writes to `Stdout` must be executed with care.
+///
+/// Created by the [`stdout`] function.
+///
+/// [`stdout`]: fn.stdout.html
+/// [`AsyncWrite`]: trait.AsyncWrite.html
+#[derive(Debug)]
+pub struct Stdout {
+ std: StdStdout,
+}
+
+/// Constructs a new handle to the standard output of the current process.
+///
+/// The returned handle allows writing to standard out from the within the Tokio
+/// runtime.
+pub fn stdout() -> Stdout {
+ let std = io::stdout();
+ Stdout { std }
+}
+
+impl Write for Stdout {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ ::would_block(|| self.std.write(buf))
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ ::would_block(|| self.std.flush())
+ }
+}
+
+impl AsyncWrite for Stdout {
+ fn shutdown(&mut self) -> Poll<(), io::Error> {
+ Ok(().into())
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/symlink_metadata.rs b/third_party/rust/tokio-fs/src/symlink_metadata.rs
new file mode 100644
index 0000000000..db02769e20
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/symlink_metadata.rs
@@ -0,0 +1,49 @@
+use super::blocking_io;
+
+use futures::{Future, Poll};
+
+use std::fs::{self, Metadata};
+use std::io;
+use std::path::Path;
+
+/// Queries the file system metadata for a path.
+///
+/// This is an async version of [`std::fs::symlink_metadata`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.symlink_metadata.html
+pub fn symlink_metadata<P>(path: P) -> SymlinkMetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ SymlinkMetadataFuture::new(path)
+}
+
+/// Future returned by `symlink_metadata`.
+#[derive(Debug)]
+pub struct SymlinkMetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ path: P,
+}
+
+impl<P> SymlinkMetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ pub(crate) fn new(path: P) -> Self {
+ Self { path }
+ }
+}
+
+impl<P> Future for SymlinkMetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ type Item = Metadata;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ blocking_io(|| fs::symlink_metadata(&self.path))
+ }
+}