diff options
author | Valentin Popov <valentin@popov.link> | 2024-07-19 15:37:58 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-07-19 15:37:58 +0300 |
commit | a990de90fe41456a23e58bd087d2f107d321f3a1 (patch) | |
tree | 15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/tempfile/src/lib.rs | |
parent | 3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff) | |
download | fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip |
Deleted vendor folder
Diffstat (limited to 'vendor/tempfile/src/lib.rs')
-rw-r--r-- | vendor/tempfile/src/lib.rs | 701 |
1 files changed, 0 insertions, 701 deletions
diff --git a/vendor/tempfile/src/lib.rs b/vendor/tempfile/src/lib.rs deleted file mode 100644 index 4b6371d..0000000 --- a/vendor/tempfile/src/lib.rs +++ /dev/null @@ -1,701 +0,0 @@ -//! Temporary files and directories. -//! -//! - Use the [`tempfile()`] function for temporary files -//! - Use the [`tempdir()`] function for temporary directories. -//! -//! # Design -//! -//! This crate provides several approaches to creating temporary files and directories. -//! [`tempfile()`] relies on the OS to remove the temporary file once the last handle is closed. -//! [`TempDir`] and [`NamedTempFile`] both rely on Rust destructors for cleanup. -//! -//! When choosing between the temporary file variants, prefer `tempfile` -//! unless you either need to know the file's path or to be able to persist it. -//! -//! ## Resource Leaking -//! -//! `tempfile` will (almost) never fail to cleanup temporary resources. However `TempDir` and `NamedTempFile` will -//! fail if their destructors don't run. This is because `tempfile` relies on the OS to cleanup the -//! underlying file, while `TempDir` and `NamedTempFile` rely on rust destructors to do so. -//! Destructors may fail to run if the process exits through an unhandled signal interrupt (like `SIGINT`), -//! or if the instance is declared statically (like with [`lazy_static`]), among other possible -//! reasons. -//! -//! ## Security -//! -//! In the presence of pathological temporary file cleaner, relying on file paths is unsafe because -//! a temporary file cleaner could delete the temporary file which an attacker could then replace. -//! -//! `tempfile` doesn't rely on file paths so this isn't an issue. However, `NamedTempFile` does -//! rely on file paths for _some_ operations. See the security documentation on -//! the `NamedTempFile` type for more information. -//! -//! ## Early drop pitfall -//! -//! Because `TempDir` and `NamedTempFile` rely on their destructors for cleanup, this can lead -//! to an unexpected early removal of the directory/file, usually when working with APIs which are -//! generic over `AsRef<Path>`. Consider the following example: -//! -//! ```no_run -//! # use tempfile::tempdir; -//! # use std::io; -//! # use std::process::Command; -//! # fn main() { -//! # if let Err(_) = run() { -//! # ::std::process::exit(1); -//! # } -//! # } -//! # fn run() -> Result<(), io::Error> { -//! // Create a directory inside of `std::env::temp_dir()`. -//! let temp_dir = tempdir()?; -//! -//! // Spawn the `touch` command inside the temporary directory and collect the exit status -//! // Note that `temp_dir` is **not** moved into `current_dir`, but passed as a reference -//! let exit_status = Command::new("touch").arg("tmp").current_dir(&temp_dir).status()?; -//! assert!(exit_status.success()); -//! -//! # Ok(()) -//! # } -//! ``` -//! -//! This works because a reference to `temp_dir` is passed to `current_dir`, resulting in the -//! destructor of `temp_dir` being run after the `Command` has finished execution. Moving the -//! `TempDir` into the `current_dir` call would result in the `TempDir` being converted into -//! an internal representation, with the original value being dropped and the directory thus -//! being deleted, before the command can be executed. -//! -//! The `touch` command would fail with an `No such file or directory` error. -//! -//! ## Examples -//! -//! Create a temporary file and write some data into it: -//! -//! ``` -//! use tempfile::tempfile; -//! use std::io::{self, Write}; -//! -//! # fn main() { -//! # if let Err(_) = run() { -//! # ::std::process::exit(1); -//! # } -//! # } -//! # fn run() -> Result<(), io::Error> { -//! // Create a file inside of `std::env::temp_dir()`. -//! let mut file = tempfile()?; -//! -//! writeln!(file, "Brian was here. Briefly.")?; -//! # Ok(()) -//! # } -//! ``` -//! -//! Create a named temporary file and open an independent file handle: -//! -//! ``` -//! use tempfile::NamedTempFile; -//! use std::io::{self, Write, Read}; -//! -//! # fn main() { -//! # if let Err(_) = run() { -//! # ::std::process::exit(1); -//! # } -//! # } -//! # fn run() -> Result<(), io::Error> { -//! let text = "Brian was here. Briefly."; -//! -//! // Create a file inside of `std::env::temp_dir()`. -//! let mut file1 = NamedTempFile::new()?; -//! -//! // Re-open it. -//! let mut file2 = file1.reopen()?; -//! -//! // Write some test data to the first handle. -//! file1.write_all(text.as_bytes())?; -//! -//! // Read the test data using the second handle. -//! let mut buf = String::new(); -//! file2.read_to_string(&mut buf)?; -//! assert_eq!(buf, text); -//! # Ok(()) -//! # } -//! ``` -//! -//! Create a temporary directory and add a file to it: -//! -//! ``` -//! use tempfile::tempdir; -//! use std::fs::File; -//! use std::io::{self, Write}; -//! -//! # fn main() { -//! # if let Err(_) = run() { -//! # ::std::process::exit(1); -//! # } -//! # } -//! # fn run() -> Result<(), io::Error> { -//! // Create a directory inside of `std::env::temp_dir()`. -//! let dir = tempdir()?; -//! -//! let file_path = dir.path().join("my-temporary-note.txt"); -//! let mut file = File::create(file_path)?; -//! writeln!(file, "Brian was here. Briefly.")?; -//! -//! // By closing the `TempDir` explicitly, we can check that it has -//! // been deleted successfully. If we don't close it explicitly, -//! // the directory will still be deleted when `dir` goes out -//! // of scope, but we won't know whether deleting the directory -//! // succeeded. -//! drop(file); -//! dir.close()?; -//! # Ok(()) -//! # } -//! ``` -//! -//! [`tempfile()`]: fn.tempfile.html -//! [`tempdir()`]: fn.tempdir.html -//! [`TempDir`]: struct.TempDir.html -//! [`NamedTempFile`]: struct.NamedTempFile.html -//! [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html -//! [`lazy_static`]: https://github.com/rust-lang-nursery/lazy-static.rs/issues/62 - -#![doc( - html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/tempfile/3.1.0" -)] -#![cfg_attr(test, deny(warnings))] -#![deny(rust_2018_idioms)] -#![allow(clippy::redundant_field_names)] -#![cfg_attr(all(feature = "nightly", target_os = "wasi"), feature(wasi_ext))] - -#[cfg(doctest)] -doc_comment::doctest!("../README.md"); - -const NUM_RETRIES: u32 = 1 << 31; -const NUM_RAND_CHARS: usize = 6; - -use std::ffi::OsStr; -use std::fs::OpenOptions; -use std::path::Path; -use std::{env, io}; - -mod dir; -mod error; -mod file; -mod spooled; -mod util; - -pub use crate::dir::{tempdir, tempdir_in, TempDir}; -pub use crate::file::{ - tempfile, tempfile_in, NamedTempFile, PathPersistError, PersistError, TempPath, -}; -pub use crate::spooled::{spooled_tempfile, SpooledTempFile}; - -/// Create a new temporary file or directory with custom parameters. -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct Builder<'a, 'b> { - random_len: usize, - prefix: &'a OsStr, - suffix: &'b OsStr, - append: bool, -} - -impl<'a, 'b> Default for Builder<'a, 'b> { - fn default() -> Self { - Builder { - random_len: crate::NUM_RAND_CHARS, - prefix: OsStr::new(".tmp"), - suffix: OsStr::new(""), - append: false, - } - } -} - -impl<'a, 'b> Builder<'a, 'b> { - /// Create a new `Builder`. - /// - /// # Examples - /// - /// Create a named temporary file and write some data into it: - /// - /// ``` - /// # use std::io; - /// # use std::ffi::OsStr; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// use tempfile::Builder; - /// - /// let named_tempfile = Builder::new() - /// .prefix("my-temporary-note") - /// .suffix(".txt") - /// .rand_bytes(5) - /// .tempfile()?; - /// - /// let name = named_tempfile - /// .path() - /// .file_name().and_then(OsStr::to_str); - /// - /// if let Some(name) = name { - /// assert!(name.starts_with("my-temporary-note")); - /// assert!(name.ends_with(".txt")); - /// assert_eq!(name.len(), "my-temporary-note.txt".len() + 5); - /// } - /// # Ok(()) - /// # } - /// ``` - /// - /// Create a temporary directory and add a file to it: - /// - /// ``` - /// # use std::io::{self, Write}; - /// # use std::fs::File; - /// # use std::ffi::OsStr; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// use tempfile::Builder; - /// - /// let dir = Builder::new() - /// .prefix("my-temporary-dir") - /// .rand_bytes(5) - /// .tempdir()?; - /// - /// let file_path = dir.path().join("my-temporary-note.txt"); - /// let mut file = File::create(file_path)?; - /// writeln!(file, "Brian was here. Briefly.")?; - /// - /// // By closing the `TempDir` explicitly, we can check that it has - /// // been deleted successfully. If we don't close it explicitly, - /// // the directory will still be deleted when `dir` goes out - /// // of scope, but we won't know whether deleting the directory - /// // succeeded. - /// drop(file); - /// dir.close()?; - /// # Ok(()) - /// # } - /// ``` - /// - /// Create a temporary directory with a chosen prefix under a chosen folder: - /// - /// ```ignore - /// let dir = Builder::new() - /// .prefix("my-temporary-dir") - /// .tempdir_in("folder-with-tempdirs")?; - /// ``` - #[must_use] - pub fn new() -> Self { - Self::default() - } - - /// Set a custom filename prefix. - /// - /// Path separators are legal but not advisable. - /// Default: `.tmp`. - /// - /// # Examples - /// - /// ``` - /// # use std::io; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// # use tempfile::Builder; - /// let named_tempfile = Builder::new() - /// .prefix("my-temporary-note") - /// .tempfile()?; - /// # Ok(()) - /// # } - /// ``` - pub fn prefix<S: AsRef<OsStr> + ?Sized>(&mut self, prefix: &'a S) -> &mut Self { - self.prefix = prefix.as_ref(); - self - } - - /// Set a custom filename suffix. - /// - /// Path separators are legal but not advisable. - /// Default: empty. - /// - /// # Examples - /// - /// ``` - /// # use std::io; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// # use tempfile::Builder; - /// let named_tempfile = Builder::new() - /// .suffix(".txt") - /// .tempfile()?; - /// # Ok(()) - /// # } - /// ``` - pub fn suffix<S: AsRef<OsStr> + ?Sized>(&mut self, suffix: &'b S) -> &mut Self { - self.suffix = suffix.as_ref(); - self - } - - /// Set the number of random bytes. - /// - /// Default: `6`. - /// - /// # Examples - /// - /// ``` - /// # use std::io; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// # use tempfile::Builder; - /// let named_tempfile = Builder::new() - /// .rand_bytes(5) - /// .tempfile()?; - /// # Ok(()) - /// # } - /// ``` - pub fn rand_bytes(&mut self, rand: usize) -> &mut Self { - self.random_len = rand; - self - } - - /// Set the file to be opened in append mode. - /// - /// Default: `false`. - /// - /// # Examples - /// - /// ``` - /// # use std::io; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// # use tempfile::Builder; - /// let named_tempfile = Builder::new() - /// .append(true) - /// .tempfile()?; - /// # Ok(()) - /// # } - /// ``` - pub fn append(&mut self, append: bool) -> &mut Self { - self.append = append; - self - } - - /// Create the named temporary file. - /// - /// # Security - /// - /// See [the security][security] docs on `NamedTempFile`. - /// - /// # Resource leaking - /// - /// See [the resource leaking][resource-leaking] docs on `NamedTempFile`. - /// - /// # Errors - /// - /// If the file cannot be created, `Err` is returned. - /// - /// # Examples - /// - /// ``` - /// # use std::io; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// # use tempfile::Builder; - /// let tempfile = Builder::new().tempfile()?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [security]: struct.NamedTempFile.html#security - /// [resource-leaking]: struct.NamedTempFile.html#resource-leaking - pub fn tempfile(&self) -> io::Result<NamedTempFile> { - self.tempfile_in(env::temp_dir()) - } - - /// Create the named temporary file in the specified directory. - /// - /// # Security - /// - /// See [the security][security] docs on `NamedTempFile`. - /// - /// # Resource leaking - /// - /// See [the resource leaking][resource-leaking] docs on `NamedTempFile`. - /// - /// # Errors - /// - /// If the file cannot be created, `Err` is returned. - /// - /// # Examples - /// - /// ``` - /// # use std::io; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// # use tempfile::Builder; - /// let tempfile = Builder::new().tempfile_in("./")?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [security]: struct.NamedTempFile.html#security - /// [resource-leaking]: struct.NamedTempFile.html#resource-leaking - pub fn tempfile_in<P: AsRef<Path>>(&self, dir: P) -> io::Result<NamedTempFile> { - util::create_helper( - dir.as_ref(), - self.prefix, - self.suffix, - self.random_len, - |path| file::create_named(path, OpenOptions::new().append(self.append)), - ) - } - - /// Attempts to make a temporary directory inside of `env::temp_dir()` whose - /// name will have the prefix, `prefix`. The directory and - /// everything inside it will be automatically deleted once the - /// returned `TempDir` is destroyed. - /// - /// # Resource leaking - /// - /// See [the resource leaking][resource-leaking] docs on `TempDir`. - /// - /// # Errors - /// - /// If the directory can not be created, `Err` is returned. - /// - /// # Examples - /// - /// ``` - /// use std::fs::File; - /// use std::io::Write; - /// use tempfile::Builder; - /// - /// # use std::io; - /// # fn run() -> Result<(), io::Error> { - /// let tmp_dir = Builder::new().tempdir()?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [resource-leaking]: struct.TempDir.html#resource-leaking - pub fn tempdir(&self) -> io::Result<TempDir> { - self.tempdir_in(env::temp_dir()) - } - - /// Attempts to make a temporary directory inside of `dir`. - /// The directory and everything inside it will be automatically - /// deleted once the returned `TempDir` is destroyed. - /// - /// # Resource leaking - /// - /// See [the resource leaking][resource-leaking] docs on `TempDir`. - /// - /// # Errors - /// - /// If the directory can not be created, `Err` is returned. - /// - /// # Examples - /// - /// ``` - /// use std::fs::{self, File}; - /// use std::io::Write; - /// use tempfile::Builder; - /// - /// # use std::io; - /// # fn run() -> Result<(), io::Error> { - /// let tmp_dir = Builder::new().tempdir_in("./")?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [resource-leaking]: struct.TempDir.html#resource-leaking - pub fn tempdir_in<P: AsRef<Path>>(&self, dir: P) -> io::Result<TempDir> { - let storage; - let mut dir = dir.as_ref(); - if !dir.is_absolute() { - let cur_dir = env::current_dir()?; - storage = cur_dir.join(dir); - dir = &storage; - } - - util::create_helper(dir, self.prefix, self.suffix, self.random_len, dir::create) - } - - /// Attempts to create a temporary file (or file-like object) using the - /// provided closure. The closure is passed a temporary file path and - /// returns an [`std::io::Result`]. The path provided to the closure will be - /// inside of [`std::env::temp_dir()`]. Use [`Builder::make_in`] to provide - /// a custom temporary directory. If the closure returns one of the - /// following errors, then another randomized file path is tried: - /// - [`std::io::ErrorKind::AlreadyExists`] - /// - [`std::io::ErrorKind::AddrInUse`] - /// - /// This can be helpful for taking full control over the file creation, but - /// leaving the temporary file path construction up to the library. This - /// also enables creating a temporary UNIX domain socket, since it is not - /// possible to bind to a socket that already exists. - /// - /// Note that [`Builder::append`] is ignored when using [`Builder::make`]. - /// - /// # Security - /// - /// This has the same [security implications][security] as - /// [`NamedTempFile`], but with additional caveats. Specifically, it is up - /// to the closure to ensure that the file does not exist and that such a - /// check is *atomic*. Otherwise, a [time-of-check to time-of-use - /// bug][TOCTOU] could be introduced. - /// - /// For example, the following is **not** secure: - /// - /// ``` - /// # use std::io; - /// # use std::fs::File; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// # use tempfile::Builder; - /// // This is NOT secure! - /// let tempfile = Builder::new().make(|path| { - /// if path.is_file() { - /// return Err(io::ErrorKind::AlreadyExists.into()); - /// } - /// - /// // Between the check above and the usage below, an attacker could - /// // have replaced `path` with another file, which would get truncated - /// // by `File::create`. - /// - /// File::create(path) - /// })?; - /// # Ok(()) - /// # } - /// ``` - /// Note that simply using [`std::fs::File::create`] alone is not correct - /// because it does not fail if the file already exists: - /// ``` - /// # use std::io; - /// # use std::fs::File; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// # use tempfile::Builder; - /// // This could overwrite an existing file! - /// let tempfile = Builder::new().make(|path| File::create(path))?; - /// # Ok(()) - /// # } - /// ``` - /// For creating regular temporary files, use [`Builder::tempfile`] instead - /// to avoid these problems. This function is meant to enable more exotic - /// use-cases. - /// - /// # Resource leaking - /// - /// See [the resource leaking][resource-leaking] docs on `NamedTempFile`. - /// - /// # Errors - /// - /// If the closure returns any error besides - /// [`std::io::ErrorKind::AlreadyExists`] or - /// [`std::io::ErrorKind::AddrInUse`], then `Err` is returned. - /// - /// # Examples - /// ``` - /// # use std::io; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// # use tempfile::Builder; - /// # #[cfg(unix)] - /// use std::os::unix::net::UnixListener; - /// # #[cfg(unix)] - /// let tempsock = Builder::new().make(|path| UnixListener::bind(path))?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [TOCTOU]: https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use - /// [security]: struct.NamedTempFile.html#security - /// [resource-leaking]: struct.NamedTempFile.html#resource-leaking - pub fn make<F, R>(&self, f: F) -> io::Result<NamedTempFile<R>> - where - F: FnMut(&Path) -> io::Result<R>, - { - self.make_in(env::temp_dir(), f) - } - - /// This is the same as [`Builder::make`], except `dir` is used as the base - /// directory for the temporary file path. - /// - /// See [`Builder::make`] for more details and security implications. - /// - /// # Examples - /// ``` - /// # use std::io; - /// # fn main() { - /// # if let Err(_) = run() { - /// # ::std::process::exit(1); - /// # } - /// # } - /// # fn run() -> Result<(), io::Error> { - /// # use tempfile::Builder; - /// # #[cfg(unix)] - /// use std::os::unix::net::UnixListener; - /// # #[cfg(unix)] - /// let tempsock = Builder::new().make_in("./", |path| UnixListener::bind(path))?; - /// # Ok(()) - /// # } - /// ``` - pub fn make_in<F, R, P>(&self, dir: P, mut f: F) -> io::Result<NamedTempFile<R>> - where - F: FnMut(&Path) -> io::Result<R>, - P: AsRef<Path>, - { - util::create_helper( - dir.as_ref(), - self.prefix, - self.suffix, - self.random_len, - move |path| { - Ok(NamedTempFile::from_parts( - f(&path)?, - TempPath::from_path(path), - )) - }, - ) - } -} |