Initial import of tempfile-3.2.0

Bug: 204072128
Test: N/A
Change-Id: Ib5769c427b50ce7cef82d519a2f592b4ea27ad79
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..d89798f
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,508 @@
+//! 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, but `TempDir` and `NamedTempFile` will 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 their destructors to do so.
+//!
+//! ## 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.
+//!
+//! ## 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
+
+#![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(feature = "nightly", feature(wasi_ext))]
+
+#[macro_use]
+extern crate cfg_if;
+
+#[cfg(doctest)]
+#[macro_use]
+extern crate doc_comment;
+
+#[cfg(doctest)]
+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(())
+    /// # }
+    /// ```
+    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)
+    }
+}