aboutsummaryrefslogtreecommitdiff
path: root/vendor/tempfile/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tempfile/src/lib.rs')
-rw-r--r--vendor/tempfile/src/lib.rs701
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),
- ))
- },
- )
- }
-}