820 lines
24 KiB
Rust
820 lines
24 KiB
Rust
#![deny(missing_docs)]
|
||
|
||
//! # Actix FS
|
||
//! _Asyncronous filesystem operations for actix-based systems_
|
||
//!
|
||
//! ## Usage
|
||
//!
|
||
//! ```rust
|
||
//! use std::io::SeekFrom;
|
||
//!
|
||
//! #[actix_rt::main]
|
||
//! async fn main() -> Result<()> {
|
||
//! let file = actix_fs::file::open("tests/read.txt").await?;
|
||
//! let (file, position) = actix_fs::file::seek(file, SeekFrom::Start(7)).await?;
|
||
//! let bytes = actix_fs::file::read(file).await?;
|
||
//!
|
||
//! assert!(position == 7);
|
||
//! assert!(bytes.as_ref() == b"World!\n");
|
||
//! Ok(())
|
||
//! }
|
||
//! ```
|
||
//!
|
||
//! ### Contributing
|
||
//! Unless otherwise stated, all contributions to this project will be licensed under the CSL with
|
||
//! the exceptions listed in the License section of this file.
|
||
//!
|
||
//! ### License
|
||
//! This work is licensed under the Cooperative Software License. This is not a Free Software
|
||
//! License, but may be considered a "source-available License." For most hobbyists, self-employed
|
||
//! developers, worker-owned companies, and cooperatives, this software can be used in most
|
||
//! projects so long as this software is distributed under the terms of the CSL. For more
|
||
//! information, see the provided LICENSE file. If none exists, the license can be found online
|
||
//! [here](https://lynnesbian.space/csl/). If you are a free software project and wish to use this
|
||
//! software under the terms of the GNU Affero General Public License, please contact me at
|
||
//! [asonix@asonix.dog](mailto:asonix@asonix.dog) and we can sort that out. If you wish to use this
|
||
//! project under any other license, especially in proprietary software, the answer is likely no.
|
||
//!
|
||
//! Actix FS is currently licensed under the AGPL to the Lemmy project, found
|
||
//! at [github.com/LemmyNet/lemmy](https://github.com/LemmyNet/lemmy)
|
||
use actix_threadpool::run;
|
||
use bytes::Bytes;
|
||
use futures::stream::Stream;
|
||
use std::{
|
||
fs, io,
|
||
path::{Path, PathBuf},
|
||
};
|
||
|
||
pub mod file;
|
||
|
||
#[derive(Debug, thiserror::Error)]
|
||
/// Possible errors produced by Actix FS
|
||
pub enum Error {
|
||
/// IO Error
|
||
#[error("{0}")]
|
||
Io(#[from] io::Error),
|
||
|
||
/// Task canceled (due to panic)
|
||
#[error("Task canceled")]
|
||
Canceled,
|
||
}
|
||
|
||
/// Actix FS Result type
|
||
pub type Result<T> = std::result::Result<T, Error>;
|
||
|
||
impl Error {
|
||
/// Get the io::ErrorKind from the error if present
|
||
///
|
||
/// This method returns None if the IO operation panicked.
|
||
pub fn kind(&self) -> Option<io::ErrorKind> {
|
||
match self {
|
||
Error::Io(ref io) => Some(io.kind()),
|
||
_ => None,
|
||
}
|
||
}
|
||
}
|
||
|
||
impl From<std::str::Utf8Error> for Error {
|
||
fn from(e: std::str::Utf8Error) -> Self {
|
||
Error::Io(io::Error::new(io::ErrorKind::InvalidInput, e))
|
||
}
|
||
}
|
||
|
||
/// Returns the canonical, absolute form of a path with all intermediate
|
||
/// components normalized and symbolic links resolved.
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `realpath` function on Unix
|
||
/// and the `CreateFile` and `GetFinalPathNameByHandle` functions on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// On Windows, this converts the path to use [extended length path][path]
|
||
/// syntax, which allows your program to use longer path names, but means you
|
||
/// can only join backslash-delimited paths to it, and it may be incompatible
|
||
/// with other applications (if passed to the application on the command-line,
|
||
/// or written to a file another application may read).
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
/// [path]: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * `path` does not exist.
|
||
/// * A non-final component in path is not a directory.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// let path = actix_fs::canonicalize("../a/../foo.txt").await?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn canonicalize<P>(path: P) -> Result<PathBuf>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
let path = run(move || fs::canonicalize(path)).await?;
|
||
|
||
Ok(path)
|
||
}
|
||
|
||
/// Copies the contents of one file to another. This function will also
|
||
/// copy the permission bits of the original file to the destination file.
|
||
///
|
||
/// This function will **overwrite** the contents of `to`.
|
||
///
|
||
/// Note that if `from` and `to` both point to the same file, then the file
|
||
/// will likely get truncated by this operation.
|
||
///
|
||
/// On success, the total number of bytes copied is returned and it is equal to
|
||
/// the length of the `to` file as reported by `metadata`.
|
||
///
|
||
/// If you’re wanting to copy the contents of one file to another and you’re
|
||
/// working with [`File`]s, see the [`io::copy`] function.
|
||
///
|
||
/// [`io::copy`]: ../io/fn.copy.html
|
||
/// [`File`]: ./struct.File.html
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `open` function in Unix
|
||
/// with `O_RDONLY` for `from` and `O_WRONLY`, `O_CREAT`, and `O_TRUNC` for `to`.
|
||
/// `O_CLOEXEC` is set for returned file descriptors.
|
||
/// On Windows, this function currently corresponds to `CopyFileEx`. Alternate
|
||
/// NTFS streams are copied but only the size of the main stream is returned by
|
||
/// this function. On MacOS, this function corresponds to `fclonefileat` and
|
||
/// `fcopyfile`.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * The `from` path is not a file.
|
||
/// * The `from` file does not exist.
|
||
/// * The current process does not have the permission rights to access
|
||
/// `from` or write `to`.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// fn main() -> actix_fs::Result<()> {
|
||
/// actix_fs::copy("foo.txt", "bar.txt").await?; // Copy foo.txt to bar.txt
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn copy<P, Q>(from: P, to: Q) -> Result<u64>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
Q: AsRef<Path> + Send + 'static,
|
||
{
|
||
let bytes = run(move || fs::copy(from, to)).await?;
|
||
|
||
Ok(bytes)
|
||
}
|
||
|
||
/// Creates a new, empty directory at the provided path
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `mkdir` function on Unix
|
||
/// and the `CreateDirectory` function on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// **NOTE**: If a parent of the given path doesn't exist, this function will
|
||
/// return an error. To create a directory and all its missing parents at the
|
||
/// same time, use the [`create_dir_all`] function.
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * User lacks permissions to create directory at `path`.
|
||
/// * A parent of the given path doesn't exist. (To create a directory and all
|
||
/// its missing parents at the same time, use the [`create_dir_all`]
|
||
/// function.)
|
||
/// * `path` already exists.
|
||
///
|
||
/// [`create_dir_all`]: fn.create_dir_all.html
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// actix_fs::create_dir("/some/dir").await?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn create_dir<P>(path: P) -> Result<()>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
run(move || fs::create_dir(path)).await?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Recursively create a directory and all of its parent components if they
|
||
/// are missing.
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `mkdir` function on Unix
|
||
/// and the `CreateDirectory` function on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * If any directory in the path specified by `path`
|
||
/// does not already exist and it could not be created otherwise. The specific
|
||
/// error conditions for when a directory is being created (after it is
|
||
/// determined to not exist) are outlined by [`fs::create_dir`].
|
||
///
|
||
/// Notable exception is made for situations where any of the directories
|
||
/// specified in the `path` could not be created as it was being created concurrently.
|
||
/// Such cases are considered to be successful. That is, calling `create_dir_all`
|
||
/// concurrently from multiple threads or processes is guaranteed not to fail
|
||
/// due to a race condition with itself.
|
||
///
|
||
/// [`fs::create_dir`]: fn.create_dir.html
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// actix_fs::create_dir_all("/some/dir").await?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn create_dir_all<P>(path: P) -> Result<()>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
run(move || fs::create_dir_all(path)).await?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 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.
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `link` function on Unix
|
||
/// and the `CreateHardLink` function on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * The `src` path is not a file or doesn't exist.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// actix_fs::hard_link("a.txt", "b.txt").await?; // Hard link a.txt to b.txt
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn hard_link<P, Q>(src: P, dst: Q) -> Result<()>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
Q: AsRef<Path> + Send + 'static,
|
||
{
|
||
run(move || fs::hard_link(src, dst)).await?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Given a path, query the file system to get information about a file,
|
||
/// directory, etc.
|
||
///
|
||
/// This function will traverse symbolic links to query information about the
|
||
/// destination file.
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `stat` function on Unix
|
||
/// and the `GetFileAttributesEx` function on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * The user lacks permissions to perform `metadata` call on `path`.
|
||
/// * `path` does not exist.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```rust,no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// let attr = actix_fs::metadata("/some/file/path.txt").await?;
|
||
/// // inspect attr ...
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn metadata<P>(path: P) -> Result<fs::Metadata>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
let metadata = run(move || fs::metadata(path)).await?;
|
||
|
||
Ok(metadata)
|
||
}
|
||
|
||
/// Read the entire contents of a file into a bytes vector.
|
||
///
|
||
/// This is a convenience function for using [`File::open`] and [`read_to_end`]
|
||
/// with fewer imports and without an intermediate variable. It pre-allocates a
|
||
/// buffer based on the file size when available, so it is generally faster than
|
||
/// reading into a vector created with `Vec::new()`.
|
||
///
|
||
/// [`file::open`]: struct.File.html#method.open
|
||
/// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error if `path` does not already exist.
|
||
/// Other errors may also be returned according to [`OpenOptions::open`].
|
||
///
|
||
/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
|
||
///
|
||
/// It will also return an error if it encounters while reading an error
|
||
/// of a kind other than [`ErrorKind::Interrupted`].
|
||
///
|
||
/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// use std::net::SocketAddr;
|
||
///
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
|
||
/// let foo: SocketAddr = String::from_utf8_lossy(&actix_fs::read("address.txt").await?).parse()?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn read<P>(path: P) -> Result<Bytes>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
let f = file::open(path).await?;
|
||
|
||
file::read(f).await
|
||
}
|
||
|
||
/// Reads a symbolic link, returning the file that the link points to.
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `readlink` function on Unix
|
||
/// and the `CreateFile` function with `FILE_FLAG_OPEN_REPARSE_POINT` and
|
||
/// `FILE_FLAG_BACKUP_SEMANTICS` flags on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * `path` is not a symbolic link.
|
||
/// * `path` does not exist.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// let path = actix_fs::read_link("a.txt").await?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn read_link<P>(path: P) -> Result<PathBuf>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
let path = run(move || fs::read_link(path)).await?;
|
||
|
||
Ok(path)
|
||
}
|
||
|
||
/// Read the contents of a file stream of bytes.
|
||
///
|
||
/// This is a convenience function for using [`file::open`] and [`read_to_stream`]
|
||
/// with fewer imports and without an intermediate variable.
|
||
///
|
||
/// [`file::open`]: struct.File.html#method.open
|
||
/// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error if `path` does not already exist.
|
||
/// Other errors may also be returned according to [`OpenOptions::open`].
|
||
///
|
||
/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// use std::net::SocketAddr;
|
||
///
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// let mut stream = actix_fs::read_to_stream("some.txt").await?;
|
||
///
|
||
/// while let Some(res) = stream.next().await {
|
||
/// println!("bytes: {:?}", res?);
|
||
/// }
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn read_to_stream<P>(path: P) -> Result<file::FileStream>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
let f = file::open(path).await?;
|
||
|
||
file::read_to_stream(f).await
|
||
}
|
||
|
||
/// Read the entire contents of a file into a string.
|
||
///
|
||
/// This is a convenience function for using [`File::open`] and [`read_to_string`]
|
||
/// with fewer imports and without an intermediate variable. It pre-allocates a
|
||
/// buffer based on the file size when available, so it is generally faster than
|
||
/// reading into a string created with `String::new()`.
|
||
///
|
||
/// [`file::open`]: struct.File.html#method.open
|
||
/// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error if `path` does not already exist.
|
||
/// Other errors may also be returned according to [`OpenOptions::open`].
|
||
///
|
||
/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
|
||
///
|
||
/// It will also return an error if it encounters while reading an error
|
||
/// of a kind other than [`ErrorKind::Interrupted`],
|
||
/// or if the contents of the file are not valid UTF-8.
|
||
///
|
||
/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// use std::net::SocketAddr;
|
||
///
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
|
||
/// let foo: SocketAddr = actix_fs::read_to_string("address.txt").await?.parse()?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn read_to_string<P>(path: P) -> Result<String>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
let f = file::open(path).await?;
|
||
|
||
file::read_to_string(f).await
|
||
}
|
||
|
||
/// Removes an existing, empty directory.
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `rmdir` function on Unix
|
||
/// and the `RemoveDirectory` function on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * The user lacks permissions to remove the directory at the provided `path`.
|
||
/// * The directory isn't empty.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// actix_fs::remove_dir("/some/dir").await?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn remove_dir<P>(path: P) -> Result<()>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
run(move || fs::remove_dir(path)).await?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Removes a directory at this path, after removing all its contents. Use
|
||
/// carefully!
|
||
///
|
||
/// This function does **not** follow symbolic links and it will simply remove the
|
||
/// symbolic link itself.
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to `opendir`, `lstat`, `rm` and `rmdir` functions on Unix
|
||
/// and the `FindFirstFile`, `GetFileAttributesEx`, `DeleteFile`, and `RemoveDirectory` functions
|
||
/// on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// See [`actix_fs::remove_file`] and [`actix_fs::remove_dir`].
|
||
///
|
||
/// [`actix_fs::remove_file`]: fn.remove_file.html
|
||
/// [`actix_fs::remove_dir`]: fn.remove_dir.html
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// actix_fs::remove_dir_all("/some/dir").await?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn remove_dir_all<P>(path: P) -> Result<()>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
run(move || fs::remove_dir_all(path)).await?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 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).
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `unlink` function on Unix
|
||
/// and the `DeleteFile` function on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * `path` points to a directory.
|
||
/// * The user lacks permissions to remove the file.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// actix_fs::remove_file("a.txt").await?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn remove_file<P>(path: P) -> Result<()>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
run(move || fs::remove_file(path)).await?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 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.
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `rename` function on Unix
|
||
/// and the `MoveFileEx` function with the `MOVEFILE_REPLACE_EXISTING` flag on Windows.
|
||
///
|
||
/// Because of this, the behavior when both `from` and `to` exist differs. On
|
||
/// Unix, if `from` is a directory, `to` must also be an (empty) directory. If
|
||
/// `from` is not a directory, `to` must also be not a directory. In contrast,
|
||
/// on Windows, `from` can be anything, but `to` must *not* be a directory.
|
||
///
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * `from` does not exist.
|
||
/// * The user lacks permissions to view contents.
|
||
/// * `from` and `to` are on separate filesystems.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// actix_fs::rename("a.txt", "b.txt").await?; // Rename a.txt to b.txt
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn rename<P, Q>(from: P, to: Q) -> Result<()>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
Q: AsRef<Path> + Send + 'static,
|
||
{
|
||
run(move || fs::rename(from, to)).await?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Changes the permissions found on a file or a directory.
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `chmod` function on Unix
|
||
/// and the `SetFileAttributes` function on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * `path` does not exist.
|
||
/// * The user lacks the permission to change attributes of the file.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// let mut perms = actix_fs::metadata("foo.txt").await?.permissions();
|
||
/// perms.set_readonly(true);
|
||
/// actix_fs::set_permissions("foo.txt", perms).await?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn set_permissions<P>(path: P, permissions: fs::Permissions) -> Result<()>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
run(move || fs::set_permissions(path, permissions)).await?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Query the metadata about a file without following symlinks.
|
||
///
|
||
/// # Platform-specific behavior
|
||
///
|
||
/// This function currently corresponds to the `lstat` function on Unix
|
||
/// and the `GetFileAttributesEx` function on Windows.
|
||
/// Note that, this [may change in the future][changes].
|
||
///
|
||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||
///
|
||
/// # Errors
|
||
///
|
||
/// This function will return an error in the following situations, but is not
|
||
/// limited to just these cases:
|
||
///
|
||
/// * The user lacks permissions to perform `metadata` call on `path`.
|
||
/// * `path` does not exist.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```rust,no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// let attr = actix_fs::symlink_metadata("/some/file/path.txt").await?;
|
||
/// // inspect attr ...
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn symlink_metadata<P>(path: P) -> Result<fs::Metadata>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
{
|
||
let metadata = run(move || fs::symlink_metadata(path)).await?;
|
||
|
||
Ok(metadata)
|
||
}
|
||
|
||
/// Write bytes as the entire contents of a file.
|
||
///
|
||
/// This function will create a file if it does not exist,
|
||
/// and will entirely replace its contents if it does.
|
||
///
|
||
/// This is a convenience function for using [`File::create`] and [`write_all`]
|
||
/// with fewer imports.
|
||
///
|
||
/// [`file::create`]: struct.File.html#method.create
|
||
/// [`write_all`]: ../io/trait.Write.html#method.write_all
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// actix_fs::write("foo.txt", b"Lorem ipsum").await?;
|
||
/// actix_fs::write("bar.txt", "dolor sit").await?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn write<P, B>(path: P, contents: B) -> Result<()>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
B: Into<Bytes>,
|
||
{
|
||
let f = file::create(path).await?;
|
||
|
||
file::write(f, contents.into()).await
|
||
}
|
||
|
||
/// Write the bytes stream as the entire contents of a file.
|
||
///
|
||
/// This function will create a file if it does not exist,
|
||
/// and will entirely replace its contents if it does.
|
||
///
|
||
/// This is a convenience function for using [`File::create`] and [`write_all`]
|
||
/// with fewer imports.
|
||
///
|
||
/// [`file::create`]: struct.File.html#method.create
|
||
/// [`write_all`]: ../io/trait.Write.html#method.write_all
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```no_run
|
||
/// #[actix_rt::main]
|
||
/// async fn main() -> actix_fs::Result<()> {
|
||
/// let mut stream = actix_fs::read_to_stream("foo.txt").await?;
|
||
///
|
||
/// actix_fs::write_stream("bar.txt", stream).await?;
|
||
/// Ok(())
|
||
/// }
|
||
/// ```
|
||
pub async fn write_stream<P, S, E>(path: P, stream: S) -> Result<()>
|
||
where
|
||
P: AsRef<Path> + Send + 'static,
|
||
S: Stream<Item = Result<Bytes>> + Unpin,
|
||
E: From<Error> + Unpin,
|
||
{
|
||
let f = file::create(path).await?;
|
||
|
||
file::write_stream(f, stream).await
|
||
}
|