summaryrefslogtreecommitdiffstats
path: root/vendor/tempfile
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/tempfile
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/tempfile')
-rw-r--r--vendor/tempfile/.cargo-checksum.json2
-rw-r--r--vendor/tempfile/Cargo.toml40
-rw-r--r--vendor/tempfile/NEWS46
-rw-r--r--vendor/tempfile/README.md3
-rw-r--r--vendor/tempfile/src/dir.rs14
-rw-r--r--vendor/tempfile/src/file/imp/other.rs4
-rw-r--r--vendor/tempfile/src/file/imp/unix.rs85
-rw-r--r--vendor/tempfile/src/file/imp/windows.rs13
-rw-r--r--vendor/tempfile/src/file/mod.rs151
-rw-r--r--vendor/tempfile/src/lib.rs176
-rw-r--r--vendor/tempfile/src/spooled.rs5
-rw-r--r--vendor/tempfile/src/util.rs10
-rw-r--r--vendor/tempfile/tests/namedtempfile.rs144
-rw-r--r--vendor/tempfile/tests/tempdir.rs8
-rw-r--r--vendor/tempfile/tests/tempfile.rs7
15 files changed, 547 insertions, 161 deletions
diff --git a/vendor/tempfile/.cargo-checksum.json b/vendor/tempfile/.cargo-checksum.json
index 26f8560bc..6633ccc75 100644
--- a/vendor/tempfile/.cargo-checksum.json
+++ b/vendor/tempfile/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"685243e302f6e014de9c8e9b95596e5f63c7bf7fde42e8e66a41a6bc7fd5e803","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"8b427f5bc501764575e52ba4f9d95673cf8f6d80a86d0d06599852e1a9a20a36","NEWS":"4255c86ac140a4d08423cd05cbd0aa42ff796bb4b38579dd19cde289ee3baecd","README.md":"db6717cbd0b3cbbce5f3cdb8a80d8f2d90b1be251b4c1c647557ae0f78ec9748","src/dir.rs":"4499ff439b740f8d2f01458664e2bf72bbfdd1206226780c6a91fb309ef15707","src/error.rs":"cc7d8eace0fff11cb342158d2885d5637bfb14b24ef30755e808554772039c5f","src/file/imp/mod.rs":"f6da9fcd93f11889670a251fdd8231b5f4614e5a971b7b183f52b44af68568d5","src/file/imp/other.rs":"99c8f9f3251199fc31e7b88810134712e5725fb6fa14648696ed5cbea980fc5b","src/file/imp/unix.rs":"cf8eeceecfddc37c9eaf95a1ebe088314dc468f07fe357961d80817eef619ca4","src/file/imp/windows.rs":"03d81d71c404f0d448e1162825d6fbd57a78b4af8d4dc5287ec2e7c5a873d7cc","src/file/mod.rs":"bda4ee3998106089a4c0ccbc8e46dc22b7d3aec427487fd4e414fb132b378736","src/lib.rs":"e2b0df7e17cc6680a5bb0829d0433f069c6bf9eede2007d21e3b01a595df41a8","src/spooled.rs":"51fa1d7639027234e257d343a5d3c95f2e47899ba6a24f0abec8d4d729eba6d6","src/util.rs":"2bd80ee69009e7e36b596d0105bb00184cff04e899e9fcce2e4cc21f23dda073","tests/namedtempfile.rs":"0031cb33ae6faf45be103869b4d98af63bef4040dc489b323212eb7a7ef72a9a","tests/spooled.rs":"29e797d486d867cb6ac46d4cf126eb5868a069a4070c3f50ffa02fbb0b887934","tests/tempdir.rs":"771d555d4eaa410207d212eb3744e016e0b5a22f1f1b7199636a4fac5daaf952","tests/tempfile.rs":"92078a1e20a39af77c1daa9a422345d20c41584dd2010b4829911c8741d1c628"},"package":"5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"} \ No newline at end of file
+{"files":{"Cargo.toml":"752e39e58b556c9d16d42fdfc7f772bbe853882bf4481cfe18922599c4bfbc04","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"8b427f5bc501764575e52ba4f9d95673cf8f6d80a86d0d06599852e1a9a20a36","NEWS":"5508856b86b8e1bf4f84c8df7fe3374968bed66f8585b8108d081cc67d425108","README.md":"5fb03bad7838354c686bab80e30323385f07efeb2aa1c5c35bdff7ec203dc5fa","src/dir.rs":"7efb94008d9d14dd3c19c105f2a0dd0695e102a1057ad91d80eed2bcb97e5bd0","src/error.rs":"cc7d8eace0fff11cb342158d2885d5637bfb14b24ef30755e808554772039c5f","src/file/imp/mod.rs":"f6da9fcd93f11889670a251fdd8231b5f4614e5a971b7b183f52b44af68568d5","src/file/imp/other.rs":"501cd1b444a5821127ea831fc8018706148f2d9f47c478f502b069963a42a2c7","src/file/imp/unix.rs":"c27c8c4e8b00e8a0e06c7243f072265eba8bc8e519e7b28ddf64d02cb4d99d01","src/file/imp/windows.rs":"3c064beb4b70677929bfe6372dba113756fbd8ea27aa6a36e86090d7b860f566","src/file/mod.rs":"10c141b5467b36f913f4946716d1d361d5a29bd7bf97ba8b6bb020d748ea0821","src/lib.rs":"6303e7470c680ad785f32eb717de2e512b88c2c5da0e1684e3704471fabd7398","src/spooled.rs":"05eef6a7aa9441ab834e602c0dd3df2222dcd4bcca91c5dfbc88591fb61a391f","src/util.rs":"6761c241cc6f4b99a85e45a827acd26b4d3bdf1d4efcb43a277f788b262ce0dc","tests/namedtempfile.rs":"a37c82908ed5df89cd2800c55abadf631d04caa55f09c966c8d1fd7a559a0ba6","tests/spooled.rs":"29e797d486d867cb6ac46d4cf126eb5868a069a4070c3f50ffa02fbb0b887934","tests/tempdir.rs":"abf08594f9d9ddc6c417de413bf63f9026150378af319d857e5ac8578f3fb665","tests/tempfile.rs":"9a2f8142151a6aa2fd047aa3749f9982ece4b080a3ace0d3c58d6bdb3f883c81"},"package":"b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"} \ No newline at end of file
diff --git a/vendor/tempfile/Cargo.toml b/vendor/tempfile/Cargo.toml
index 253f8667b..85006d831 100644
--- a/vendor/tempfile/Cargo.toml
+++ b/vendor/tempfile/Cargo.toml
@@ -11,33 +11,49 @@
[package]
edition = "2018"
+rust-version = "1.48"
name = "tempfile"
-version = "3.3.0"
-authors = ["Steven Allen <steven@stebalien.com>", "The Rust Project Developers", "Ashley Mannix <ashleymannix@live.com.au>", "Jason White <jasonaw0@gmail.com>"]
-exclude = ["/.travis.yml", "/appveyor.yml"]
+version = "3.5.0"
+authors = [
+ "Steven Allen <steven@stebalien.com>",
+ "The Rust Project Developers",
+ "Ashley Mannix <ashleymannix@live.com.au>",
+ "Jason White <me@jasonwhite.io>",
+]
description = "A library for managing temporary files and directories."
-homepage = "http://stebalien.com/projects/tempfile-rs"
+homepage = "https://stebalien.com/projects/tempfile-rs/"
documentation = "https://docs.rs/tempfile"
-keywords = ["tempfile", "tmpfile", "filesystem"]
+readme = "README.md"
+keywords = [
+ "tempfile",
+ "tmpfile",
+ "filesystem",
+]
license = "MIT OR Apache-2.0"
repository = "https://github.com/Stebalien/tempfile"
+
[dependencies.cfg-if]
version = "1"
[dependencies.fastrand]
version = "1.6.0"
-[dependencies.remove_dir_all]
-version = "0.5"
[dev-dependencies.doc-comment]
version = "0.3"
[features]
nightly = []
-[target."cfg(any(unix, target_os = \"wasi\"))".dependencies.libc]
-version = "0.2.27"
+
+[target."cfg(any(unix, target_os = \"wasi\"))".dependencies.rustix]
+version = "0.37.1"
+features = ["fs"]
+
[target."cfg(target_os = \"redox\")".dependencies.redox_syscall]
-version = "0.2.9"
-[target."cfg(windows)".dependencies.winapi]
version = "0.3"
-features = ["fileapi", "handleapi", "winbase"]
+
+[target."cfg(windows)".dependencies.windows-sys]
+version = "0.45"
+features = [
+ "Win32_Storage_FileSystem",
+ "Win32_Foundation",
+]
diff --git a/vendor/tempfile/NEWS b/vendor/tempfile/NEWS
index c28442426..14f8a9e4e 100644
--- a/vendor/tempfile/NEWS
+++ b/vendor/tempfile/NEWS
@@ -1,3 +1,47 @@
+3.5.0
+=====
+
+- Update rustix from 0.36 to 0.37.1. This makes wasi work on rust stable
+- Update `windows-sys`, `redox_syscall`
+- BREAKING: Remove the implementation of `Write for &NamedTempFile<F> where &F: Write`. Unfortunately, this can cause compile issues in unrelated code (https://github.com/Stebalien/tempfile/issues/224).
+
+3.4.0
+=====
+
+SECURITY: Prior `tempfile` releases depended on `remove_dir_all` version 0.5.0 which was vulnerable to a [TOCTOU race](https://github.com/XAMPPRocky/remove_dir_all/security/advisories/GHSA-mc8h-8q98-g5hr). This same race is present in rust versions prior to 1.58.1.
+
+Features:
+
+* Generalized temporary files: `NamedTempFile` can now abstract over different kinds of files (e.g.,
+ unix domain sockets, pipes, etc.):
+ * Add `Builder::make` and `Builder::make_in` for generalized temp file
+ creation.
+ * Add `NamedTempFile::from_parts` to complement `NamedTempFile::into_parts`.
+ * Add generic parameter to `NamedTempFile` to support wrapping non-File types.
+
+Bug Fixes/Improvements:
+
+* Don't try to create a temporary file multiple times if the file path has been fully specified by
+ the user (no random characters).
+* `NamedTempFile::persist_noclobber` is now always atomic on linux when `renameat_with` is
+ supported. Previously, it would first link the new path, then unlink the previous path.
+* Fix compiler warnings on windows.
+
+Trivia:
+
+* Switch from `libc` to `rustix` on wasi/unix. This now makes direct syscalls instead of calling
+ through libc.
+* Remove `remove_dir_all` dependency. The rust standard library has optimized their internal version
+ significantly.
+ * Switch to official windows-sys windows bindings.
+
+Breaking:
+
+ * The minimum rust version is now `1.48.0`.
+ * Mark most functions as `must_use`.
+ * Uses direct syscalls on linux by default, instead of libc.
+ * The new type parameter in `NamedTempFile` may lead to type inference issues in some cases.
+
3.3.0
=====
@@ -198,7 +242,7 @@ Add LFS Support.
2.0.0
=====
-This release replaces `TempFile` with a `tempfile()` function that returnes
+This release replaces `TempFile` with a `tempfile()` function that returns
`std::fs::File` objects. These are significantly more useful because most rust
libraries expect normal `File` objects.
diff --git a/vendor/tempfile/README.md b/vendor/tempfile/README.md
index 1dba3a01d..bf207f8a4 100644
--- a/vendor/tempfile/README.md
+++ b/vendor/tempfile/README.md
@@ -14,9 +14,10 @@ patterns and surprisingly difficult to implement securely).
Usage
-----
-Minimum required Rust version: 1.40.0
+Minimum required Rust version: 1.48.0
Add this to your `Cargo.toml`:
+
```toml
[dependencies]
tempfile = "3"
diff --git a/vendor/tempfile/src/dir.rs b/vendor/tempfile/src/dir.rs
index d5a944b6f..917e47ec2 100644
--- a/vendor/tempfile/src/dir.rs
+++ b/vendor/tempfile/src/dir.rs
@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use remove_dir_all::remove_dir_all;
+use std::fs::remove_dir_all;
use std::mem;
use std::path::{self, Path, PathBuf};
use std::{fmt, fs, io};
@@ -65,9 +65,9 @@ pub fn tempdir() -> io::Result<TempDir> {
TempDir::new()
}
-/// Create a new temporary directory.
+/// Create a new temporary directory in a specific directory.
///
-/// The `tempdir` function creates a directory in the file system
+/// The `tempdir_in` function creates a directory in the specified directory
/// and returns a [`TempDir`].
/// The directory will be automatically deleted when the `TempDir`s
/// destructor is run.
@@ -83,7 +83,7 @@ pub fn tempdir() -> io::Result<TempDir> {
/// # Examples
///
/// ```
-/// use tempfile::tempdir;
+/// use tempfile::tempdir_in;
/// use std::fs::File;
/// use std::io::{self, Write};
///
@@ -93,8 +93,8 @@ pub fn tempdir() -> io::Result<TempDir> {
/// # }
/// # }
/// # fn run() -> Result<(), io::Error> {
-/// // Create a directory inside of `std::env::temp_dir()`,
-/// let dir = tempdir()?;
+/// // Create a directory inside of the current directory.
+/// let dir = tempdir_in(".")?;
///
/// let file_path = dir.path().join("my-temporary-note.txt");
/// let mut file = File::create(file_path)?;
@@ -292,6 +292,7 @@ impl TempDir {
/// # Ok(())
/// # }
/// ```
+ #[must_use]
pub fn path(&self) -> &path::Path {
self.path.as_ref()
}
@@ -323,6 +324,7 @@ impl TempDir {
/// # Ok(())
/// # }
/// ```
+ #[must_use]
pub fn into_path(self) -> PathBuf {
// Prevent the Drop impl from being called.
let mut this = mem::ManuallyDrop::new(self);
diff --git a/vendor/tempfile/src/file/imp/other.rs b/vendor/tempfile/src/file/imp/other.rs
index d8a55a745..8721d2da6 100644
--- a/vendor/tempfile/src/file/imp/other.rs
+++ b/vendor/tempfile/src/file/imp/other.rs
@@ -9,7 +9,7 @@ fn not_supported<T>() -> io::Result<T> {
))
}
-pub fn create_named(_path: &Path, open_options: &mut OpenOptions) -> io::Result<File> {
+pub fn create_named(_path: &Path, _open_options: &mut OpenOptions) -> io::Result<File> {
not_supported()
}
@@ -25,6 +25,6 @@ pub fn persist(_old_path: &Path, _new_path: &Path, _overwrite: bool) -> io::Resu
not_supported()
}
-pub fn keep(path: &Path) -> io::Result<()> {
+pub fn keep(_path: &Path) -> io::Result<()> {
not_supported()
}
diff --git a/vendor/tempfile/src/file/imp/unix.rs b/vendor/tempfile/src/file/imp/unix.rs
index 480743cf7..c305ea95e 100644
--- a/vendor/tempfile/src/file/imp/unix.rs
+++ b/vendor/tempfile/src/file/imp/unix.rs
@@ -1,13 +1,11 @@
use std::env;
-use std::ffi::{CString, OsStr};
+use std::ffi::OsStr;
use std::fs::{self, File, OpenOptions};
use std::io;
cfg_if::cfg_if! {
if #[cfg(not(target_os = "wasi"))] {
- use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::{MetadataExt, OpenOptionsExt};
} else {
- use std::os::wasi::ffi::OsStrExt;
#[cfg(feature = "nightly")]
use std::os::wasi::fs::MetadataExt;
}
@@ -16,29 +14,7 @@ use crate::util;
use std::path::Path;
#[cfg(not(target_os = "redox"))]
-use libc::{c_char, c_int, link, rename, unlink};
-
-#[cfg(not(target_os = "redox"))]
-#[inline(always)]
-pub fn cvt_err(result: c_int) -> io::Result<c_int> {
- if result == -1 {
- Err(io::Error::last_os_error())
- } else {
- Ok(result)
- }
-}
-
-#[cfg(target_os = "redox")]
-#[inline(always)]
-pub fn cvt_err(result: Result<usize, syscall::Error>) -> io::Result<usize> {
- result.map_err(|err| io::Error::from_raw_os_error(err.errno))
-}
-
-// Stolen from std.
-pub fn cstr(path: &Path) -> io::Result<CString> {
- CString::new(path.as_os_str().as_bytes())
- .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "path contained a null"))
-}
+use rustix::fs::{cwd, linkat, renameat, unlinkat, AtFlags};
pub fn create_named(path: &Path, open_options: &mut OpenOptions) -> io::Result<File> {
open_options.read(true).write(true).create_new(true);
@@ -70,16 +46,18 @@ fn create_unlinked(path: &Path) -> io::Result<File> {
#[cfg(target_os = "linux")]
pub fn create(dir: &Path) -> io::Result<File> {
- use libc::{EISDIR, ENOENT, EOPNOTSUPP, O_TMPFILE};
+ use rustix::{fs::OFlags, io::Errno};
OpenOptions::new()
.read(true)
.write(true)
- .custom_flags(O_TMPFILE) // do not mix with `create_new(true)`
+ .custom_flags(OFlags::TMPFILE.bits() as i32) // do not mix with `create_new(true)`
.open(dir)
.or_else(|e| {
- match e.raw_os_error() {
+ match Errno::from_io_error(&e) {
// These are the three "not supported" error codes for O_TMPFILE.
- Some(EOPNOTSUPP) | Some(EISDIR) | Some(ENOENT) => create_unix(dir),
+ Some(Errno::OPNOTSUPP) | Some(Errno::ISDIR) | Some(Errno::NOENT) => {
+ create_unix(dir)
+ }
_ => Err(e),
}
})
@@ -124,29 +102,40 @@ pub fn reopen(_file: &File, _path: &Path) -> io::Result<File> {
#[cfg(not(target_os = "redox"))]
pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
- unsafe {
- let old_path = cstr(old_path)?;
- let new_path = cstr(new_path)?;
- if overwrite {
- cvt_err(rename(
- old_path.as_ptr() as *const c_char,
- new_path.as_ptr() as *const c_char,
- ))?;
- } else {
- cvt_err(link(
- old_path.as_ptr() as *const c_char,
- new_path.as_ptr() as *const c_char,
- ))?;
- // Ignore unlink errors. Can we do better?
- // On recent linux, we can use renameat2 to do this atomically.
- let _ = unlink(old_path.as_ptr() as *const c_char);
+ if overwrite {
+ renameat(cwd(), old_path, cwd(), new_path)?;
+ } else {
+ // On Linux, use `renameat_with` to avoid overwriting an existing name,
+ // if the kernel and the filesystem support it.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ {
+ use rustix::fs::{renameat_with, RenameFlags};
+ use rustix::io::Errno;
+ use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
+
+ static NOSYS: AtomicBool = AtomicBool::new(false);
+ if !NOSYS.load(Relaxed) {
+ match renameat_with(cwd(), old_path, cwd(), new_path, RenameFlags::NOREPLACE) {
+ Ok(()) => return Ok(()),
+ Err(Errno::NOSYS) => NOSYS.store(true, Relaxed),
+ Err(Errno::INVAL) => {}
+ Err(e) => return Err(e.into()),
+ }
+ }
}
- Ok(())
+
+ // Otherwise use `linkat` to create the new filesystem name, which
+ // will fail if the name already exists, and then `unlinkat` to remove
+ // the old name.
+ linkat(cwd(), old_path, cwd(), new_path, AtFlags::empty())?;
+ // Ignore unlink errors. Can we do better?
+ let _ = unlinkat(cwd(), old_path, AtFlags::empty());
}
+ Ok(())
}
#[cfg(target_os = "redox")]
-pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
+pub fn persist(_old_path: &Path, _new_path: &Path, _overwrite: bool) -> io::Result<()> {
// XXX implement when possible
Err(io::Error::from_raw_os_error(syscall::ENOSYS))
}
diff --git a/vendor/tempfile/src/file/imp/windows.rs b/vendor/tempfile/src/file/imp/windows.rs
index 71b474880..cb2673b5a 100644
--- a/vendor/tempfile/src/file/imp/windows.rs
+++ b/vendor/tempfile/src/file/imp/windows.rs
@@ -6,13 +6,12 @@ use std::os::windows::io::{AsRawHandle, FromRawHandle, RawHandle};
use std::path::Path;
use std::{io, iter};
-use winapi::um::fileapi::SetFileAttributesW;
-use winapi::um::handleapi::INVALID_HANDLE_VALUE;
-use winapi::um::winbase::{MoveFileExW, ReOpenFile};
-use winapi::um::winbase::{FILE_FLAG_DELETE_ON_CLOSE, MOVEFILE_REPLACE_EXISTING};
-use winapi::um::winnt::{FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_TEMPORARY};
-use winapi::um::winnt::{FILE_GENERIC_READ, FILE_GENERIC_WRITE, HANDLE};
-use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
+use windows_sys::Win32::Foundation::{HANDLE, INVALID_HANDLE_VALUE};
+use windows_sys::Win32::Storage::FileSystem::{
+ MoveFileExW, ReOpenFile, SetFileAttributesW, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_TEMPORARY,
+ FILE_FLAG_DELETE_ON_CLOSE, FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_SHARE_DELETE,
+ FILE_SHARE_READ, FILE_SHARE_WRITE, MOVEFILE_REPLACE_EXISTING,
+};
use crate::util;
diff --git a/vendor/tempfile/src/file/mod.rs b/vendor/tempfile/src/file/mod.rs
index b859ced79..023acd26a 100644
--- a/vendor/tempfile/src/file/mod.rs
+++ b/vendor/tempfile/src/file/mod.rs
@@ -52,7 +52,7 @@ mod imp;
///
/// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
pub fn tempfile() -> io::Result<File> {
- tempfile_in(&env::temp_dir())
+ tempfile_in(env::temp_dir())
}
/// Create a new temporary file in the specified directory.
@@ -467,29 +467,31 @@ impl AsRef<OsStr> for TempPath {
/// # Resource Leaking
///
/// If the program exits before the `NamedTempFile` destructor is
-/// run, such as via [`std::process::exit()`], by segfaulting, or by
-/// receiving a signal like `SIGINT`, then the temporary file
-/// will not be deleted.
+/// run, the temporary file will not be deleted. This can happen
+/// if the process exits using [`std::process::exit()`], a segfault occurs,
+/// receiving an interrupt signal like `SIGINT` that is not handled, or by using
+/// a statically declared `NamedTempFile` instance (like with [`lazy_static`]).
///
-/// Use the [`tempfile()`] function unless you absolutely need a named file.
+/// Use the [`tempfile()`] function unless you need a named file path.
///
/// [`tempfile()`]: fn.tempfile.html
/// [`NamedTempFile::new()`]: #method.new
/// [`NamedTempFile::new_in()`]: #method.new_in
/// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
/// [`std::process::exit()`]: http://doc.rust-lang.org/std/process/fn.exit.html
-pub struct NamedTempFile {
+/// [`lazy_static`]: https://github.com/rust-lang-nursery/lazy-static.rs/issues/62
+pub struct NamedTempFile<F = File> {
path: TempPath,
- file: File,
+ file: F,
}
-impl fmt::Debug for NamedTempFile {
+impl<F> fmt::Debug for NamedTempFile<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "NamedTempFile({:?})", self.path)
}
}
-impl AsRef<Path> for NamedTempFile {
+impl<F> AsRef<Path> for NamedTempFile<F> {
#[inline]
fn as_ref(&self) -> &Path {
self.path()
@@ -497,41 +499,46 @@ impl AsRef<Path> for NamedTempFile {
}
/// Error returned when persisting a temporary file fails.
-#[derive(Debug)]
-pub struct PersistError {
+pub struct PersistError<F = File> {
/// The underlying IO error.
pub error: io::Error,
/// The temporary file that couldn't be persisted.
- pub file: NamedTempFile,
+ pub file: NamedTempFile<F>,
+}
+
+impl<F> fmt::Debug for PersistError<F> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "PersistError({:?})", self.error)
+ }
}
-impl From<PersistError> for io::Error {
+impl<F> From<PersistError<F>> for io::Error {
#[inline]
- fn from(error: PersistError) -> io::Error {
+ fn from(error: PersistError<F>) -> io::Error {
error.error
}
}
-impl From<PersistError> for NamedTempFile {
+impl<F> From<PersistError<F>> for NamedTempFile<F> {
#[inline]
- fn from(error: PersistError) -> NamedTempFile {
+ fn from(error: PersistError<F>) -> NamedTempFile<F> {
error.file
}
}
-impl fmt::Display for PersistError {
+impl<F> fmt::Display for PersistError<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "failed to persist temporary file: {}", self.error)
}
}
-impl error::Error for PersistError {
+impl<F> error::Error for PersistError<F> {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(&self.error)
}
}
-impl NamedTempFile {
+impl NamedTempFile<File> {
/// Create a new named temporary file.
///
/// See [`Builder`] for more configuration.
@@ -601,7 +608,9 @@ impl NamedTempFile {
pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<NamedTempFile> {
Builder::new().tempfile_in(dir)
}
+}
+impl<F> NamedTempFile<F> {
/// Get the temporary file's path.
///
/// # Security
@@ -711,7 +720,7 @@ impl NamedTempFile {
/// ```
///
/// [`PersistError`]: struct.PersistError.html
- pub fn persist<P: AsRef<Path>>(self, new_path: P) -> Result<File, PersistError> {
+ pub fn persist<P: AsRef<Path>>(self, new_path: P) -> Result<F, PersistError<F>> {
let NamedTempFile { path, file } = self;
match path.persist(new_path) {
Ok(_) => Ok(file),
@@ -764,7 +773,7 @@ impl NamedTempFile {
/// # Ok(())
/// # }
/// ```
- pub fn persist_noclobber<P: AsRef<Path>>(self, new_path: P) -> Result<File, PersistError> {
+ pub fn persist_noclobber<P: AsRef<Path>>(self, new_path: P) -> Result<F, PersistError<F>> {
let NamedTempFile { path, file } = self;
match path.persist_noclobber(new_path) {
Ok(_) => Ok(file),
@@ -808,7 +817,7 @@ impl NamedTempFile {
/// ```
///
/// [`PathPersistError`]: struct.PathPersistError.html
- pub fn keep(self) -> Result<(File, PathBuf), PersistError> {
+ pub fn keep(self) -> Result<(F, PathBuf), PersistError<F>> {
let (file, path) = (self.file, self.path);
match path.keep() {
Ok(path) => Ok((file, path)),
@@ -819,6 +828,49 @@ impl NamedTempFile {
}
}
+ /// Get a reference to the underlying file.
+ pub fn as_file(&self) -> &F {
+ &self.file
+ }
+
+ /// Get a mutable reference to the underlying file.
+ pub fn as_file_mut(&mut self) -> &mut F {
+ &mut self.file
+ }
+
+ /// Convert the temporary file into a `std::fs::File`.
+ ///
+ /// The inner file will be deleted.
+ pub fn into_file(self) -> F {
+ self.file
+ }
+
+ /// Closes the file, leaving only the temporary file path.
+ ///
+ /// This is useful when another process must be able to open the temporary
+ /// file.
+ pub fn into_temp_path(self) -> TempPath {
+ self.path
+ }
+
+ /// Converts the named temporary file into its constituent parts.
+ ///
+ /// Note: When the path is dropped, the file is deleted but the file handle
+ /// is still usable.
+ pub fn into_parts(self) -> (F, TempPath) {
+ (self.file, self.path)
+ }
+
+ /// Creates a `NamedTempFile` from its constituent parts.
+ ///
+ /// This can be used with [`NamedTempFile::into_parts`] to reconstruct the
+ /// `NamedTempFile`.
+ pub fn from_parts(file: F, path: TempPath) -> Self {
+ Self { file, path }
+ }
+}
+
+impl NamedTempFile<File> {
/// Securely reopen the temporary file.
///
/// This function is useful when you need multiple independent handles to
@@ -858,54 +910,21 @@ impl NamedTempFile {
imp::reopen(self.as_file(), NamedTempFile::path(self))
.with_err_path(|| NamedTempFile::path(self))
}
-
- /// Get a reference to the underlying file.
- pub fn as_file(&self) -> &File {
- &self.file
- }
-
- /// Get a mutable reference to the underlying file.
- pub fn as_file_mut(&mut self) -> &mut File {
- &mut self.file
- }
-
- /// Convert the temporary file into a `std::fs::File`.
- ///
- /// The inner file will be deleted.
- pub fn into_file(self) -> File {
- self.file
- }
-
- /// Closes the file, leaving only the temporary file path.
- ///
- /// This is useful when another process must be able to open the temporary
- /// file.
- pub fn into_temp_path(self) -> TempPath {
- self.path
- }
-
- /// Converts the named temporary file into its constituent parts.
- ///
- /// Note: When the path is dropped, the file is deleted but the file handle
- /// is still usable.
- pub fn into_parts(self) -> (File, TempPath) {
- (self.file, self.path)
- }
}
-impl Read for NamedTempFile {
+impl<F: Read> Read for NamedTempFile<F> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.as_file_mut().read(buf).with_err_path(|| self.path())
}
}
-impl<'a> Read for &'a NamedTempFile {
+impl Read for &NamedTempFile<File> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.as_file().read(buf).with_err_path(|| self.path())
}
}
-impl Write for NamedTempFile {
+impl<F: Write> Write for NamedTempFile<F> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.as_file_mut().write(buf).with_err_path(|| self.path())
}
@@ -915,7 +934,7 @@ impl Write for NamedTempFile {
}
}
-impl<'a> Write for &'a NamedTempFile {
+impl Write for &NamedTempFile<File> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.as_file().write(buf).with_err_path(|| self.path())
}
@@ -925,20 +944,23 @@ impl<'a> Write for &'a NamedTempFile {
}
}
-impl Seek for NamedTempFile {
+impl<F: Seek> Seek for NamedTempFile<F> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
self.as_file_mut().seek(pos).with_err_path(|| self.path())
}
}
-impl<'a> Seek for &'a NamedTempFile {
+impl Seek for &NamedTempFile<File> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
self.as_file().seek(pos).with_err_path(|| self.path())
}
}
#[cfg(unix)]
-impl std::os::unix::io::AsRawFd for NamedTempFile {
+impl<F> std::os::unix::io::AsRawFd for NamedTempFile<F>
+where
+ F: std::os::unix::io::AsRawFd,
+{
#[inline]
fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
self.as_file().as_raw_fd()
@@ -946,7 +968,10 @@ impl std::os::unix::io::AsRawFd for NamedTempFile {
}
#[cfg(windows)]
-impl std::os::windows::io::AsRawHandle for NamedTempFile {
+impl<F> std::os::windows::io::AsRawHandle for NamedTempFile<F>
+where
+ F: std::os::windows::io::AsRawHandle,
+{
#[inline]
fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
self.as_file().as_raw_handle()
diff --git a/vendor/tempfile/src/lib.rs b/vendor/tempfile/src/lib.rs
index c38ca7b87..4b6371d49 100644
--- a/vendor/tempfile/src/lib.rs
+++ b/vendor/tempfile/src/lib.rs
@@ -14,9 +14,12 @@
//!
//! ## 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.
+//! `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
//!
@@ -152,6 +155,7 @@
//! [`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",
@@ -161,7 +165,7 @@
#![cfg_attr(test, deny(warnings))]
#![deny(rust_2018_idioms)]
#![allow(clippy::redundant_field_names)]
-#![cfg_attr(feature = "nightly", feature(wasi_ext))]
+#![cfg_attr(all(feature = "nightly", target_os = "wasi"), feature(wasi_ext))]
#[cfg(doctest)]
doc_comment::doctest!("../README.md");
@@ -276,6 +280,15 @@ impl<'a, 'b> Builder<'a, 'b> {
/// # 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()
}
@@ -419,7 +432,7 @@ impl<'a, 'b> Builder<'a, 'b> {
/// [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())
+ self.tempfile_in(env::temp_dir())
}
/// Create the named temporary file in the specified directory.
@@ -493,7 +506,7 @@ impl<'a, 'b> Builder<'a, 'b> {
///
/// [resource-leaking]: struct.TempDir.html#resource-leaking
pub fn tempdir(&self) -> io::Result<TempDir> {
- self.tempdir_in(&env::temp_dir())
+ self.tempdir_in(env::temp_dir())
}
/// Attempts to make a temporary directory inside of `dir`.
@@ -534,4 +547,155 @@ impl<'a, 'b> Builder<'a, 'b> {
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),
+ ))
+ },
+ )
+ }
}
diff --git a/vendor/tempfile/src/spooled.rs b/vendor/tempfile/src/spooled.rs
index ed6c16fb4..db14967ca 100644
--- a/vendor/tempfile/src/spooled.rs
+++ b/vendor/tempfile/src/spooled.rs
@@ -64,14 +64,16 @@ pub fn spooled_tempfile(max_size: usize) -> SpooledTempFile {
}
impl SpooledTempFile {
+ #[must_use]
pub fn new(max_size: usize) -> SpooledTempFile {
SpooledTempFile {
- max_size: max_size,
+ max_size,
inner: SpooledData::InMemory(Cursor::new(Vec::new())),
}
}
/// Returns true if the file has been rolled over to disk.
+ #[must_use]
pub fn is_rolled(&self) -> bool {
match self.inner {
SpooledData::InMemory(_) => false,
@@ -107,6 +109,7 @@ impl SpooledTempFile {
}
/// Consumes and returns the inner `SpooledData` type.
+ #[must_use]
pub fn into_inner(self) -> SpooledData {
self.inner
}
diff --git a/vendor/tempfile/src/util.rs b/vendor/tempfile/src/util.rs
index 8c91b9c69..c61082d50 100644
--- a/vendor/tempfile/src/util.rs
+++ b/vendor/tempfile/src/util.rs
@@ -1,4 +1,3 @@
-use fastrand;
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
use std::{io, iter::repeat_with};
@@ -21,10 +20,10 @@ pub fn create_helper<F, R>(
prefix: &OsStr,
suffix: &OsStr,
random_len: usize,
- f: F,
+ mut f: F,
) -> io::Result<R>
where
- F: Fn(PathBuf) -> io::Result<R>,
+ F: FnMut(PathBuf) -> io::Result<R>,
{
let num_retries = if random_len != 0 {
crate::NUM_RETRIES
@@ -35,7 +34,10 @@ where
for _ in 0..num_retries {
let path = base.join(tmpname(prefix, suffix, random_len));
return match f(path) {
- Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => continue,
+ Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists && num_retries > 1 => continue,
+ // AddrInUse can happen if we're creating a UNIX domain socket and
+ // the path already exists.
+ Err(ref e) if e.kind() == io::ErrorKind::AddrInUse && num_retries > 1 => continue,
res => res,
};
}
diff --git a/vendor/tempfile/tests/namedtempfile.rs b/vendor/tempfile/tests/namedtempfile.rs
index d2c7da22b..54396c3ac 100644
--- a/vendor/tempfile/tests/namedtempfile.rs
+++ b/vendor/tempfile/tests/namedtempfile.rs
@@ -87,7 +87,7 @@ fn test_persist_noclobber() {
fn test_customnamed() {
let tmpfile = Builder::new()
.prefix("tmp")
- .suffix(&".rs".to_string())
+ .suffix(&".rs")
.rand_bytes(12)
.tempfile()
.unwrap();
@@ -100,9 +100,9 @@ fn test_customnamed() {
#[test]
fn test_append() {
let mut tmpfile = Builder::new().append(true).tempfile().unwrap();
- tmpfile.write(b"a").unwrap();
+ tmpfile.write_all(b"a").unwrap();
tmpfile.seek(SeekFrom::Start(0)).unwrap();
- tmpfile.write(b"b").unwrap();
+ tmpfile.write_all(b"b").unwrap();
tmpfile.seek(SeekFrom::Start(0)).unwrap();
let mut buf = vec![0u8; 1];
@@ -299,6 +299,18 @@ fn test_into_parts() {
}
#[test]
+fn test_from_parts() {
+ let mut file = NamedTempFile::new().unwrap();
+ write!(file, "abcd").expect("write failed");
+
+ let (file, temp_path) = file.into_parts();
+
+ let file = NamedTempFile::from_parts(file, temp_path);
+
+ assert!(file.path().exists());
+}
+
+#[test]
fn test_keep() {
let mut tmpfile = NamedTempFile::new().unwrap();
write!(tmpfile, "abcde").unwrap();
@@ -326,3 +338,129 @@ fn test_keep() {
}
std::fs::remove_file(&path).unwrap();
}
+
+#[test]
+fn test_make() {
+ let tmpfile = Builder::new().make(|path| File::create(path)).unwrap();
+
+ assert!(tmpfile.path().is_file());
+}
+
+#[test]
+fn test_make_in() {
+ let tmp_dir = tempdir().unwrap();
+
+ let tmpfile = Builder::new()
+ .make_in(tmp_dir.path(), |path| File::create(path))
+ .unwrap();
+
+ assert!(tmpfile.path().is_file());
+ assert_eq!(tmpfile.path().parent(), Some(tmp_dir.path()));
+}
+
+#[test]
+fn test_make_fnmut() {
+ let mut count = 0;
+
+ // Show that an FnMut can be used.
+ let tmpfile = Builder::new()
+ .make(|path| {
+ count += 1;
+ File::create(path)
+ })
+ .unwrap();
+
+ assert!(tmpfile.path().is_file());
+}
+
+#[cfg(unix)]
+#[test]
+fn test_make_uds() {
+ use std::os::unix::net::UnixListener;
+
+ let temp_sock = Builder::new()
+ .prefix("tmp")
+ .suffix(".sock")
+ .rand_bytes(12)
+ .make(|path| UnixListener::bind(path))
+ .unwrap();
+
+ assert!(temp_sock.path().exists());
+}
+
+#[cfg(unix)]
+#[test]
+fn test_make_uds_conflict() {
+ use std::os::unix::net::UnixListener;
+ use std::sync::atomic::{AtomicUsize, Ordering};
+ use std::sync::Arc;
+
+ // Check that retries happen correctly by racing N different threads.
+
+ const NTHREADS: usize = 20;
+
+ // The number of times our callback was called.
+ let tries = Arc::new(AtomicUsize::new(0));
+
+ let mut threads = Vec::with_capacity(NTHREADS);
+
+ for _ in 0..NTHREADS {
+ let tries = tries.clone();
+ threads.push(std::thread::spawn(move || {
+ // Ensure that every thread uses the same seed so we are guaranteed
+ // to retry. Note that fastrand seeds are thread-local.
+ fastrand::seed(42);
+
+ Builder::new()
+ .prefix("tmp")
+ .suffix(".sock")
+ .rand_bytes(12)
+ .make(|path| {
+ tries.fetch_add(1, Ordering::Relaxed);
+ UnixListener::bind(path)
+ })
+ }));
+ }
+
+ // Join all threads, but don't drop the temp file yet. Otherwise, we won't
+ // get a deterministic number of `tries`.
+ let sockets: Vec<_> = threads
+ .into_iter()
+ .map(|thread| thread.join().unwrap().unwrap())
+ .collect();
+
+ // Number of tries is exactly equal to (n*(n+1))/2.
+ assert_eq!(
+ tries.load(Ordering::Relaxed),
+ (NTHREADS * (NTHREADS + 1)) / 2
+ );
+
+ for socket in sockets {
+ assert!(socket.path().exists());
+ }
+}
+
+// Issue #224.
+#[test]
+fn test_overly_generic_bounds() {
+ pub struct Foo<T>(T);
+
+ impl<T> Foo<T>
+ where
+ T: Sync + Send + 'static,
+ for<'a> &'a T: Write + Read,
+ {
+ pub fn new(foo: T) -> Self {
+ Self(foo)
+ }
+ }
+
+ // Don't really need to run this. Only care if it compiles.
+ if let Ok(file) = File::open("i_do_not_exist") {
+ let mut f;
+ let _x = {
+ f = Foo::new(file);
+ &mut f
+ };
+ }
+}
diff --git a/vendor/tempfile/tests/tempdir.rs b/vendor/tempfile/tests/tempdir.rs
index 746fe4738..de9723328 100644
--- a/vendor/tempfile/tests/tempdir.rs
+++ b/vendor/tempfile/tests/tempdir.rs
@@ -67,7 +67,7 @@ fn test_customnamed() {
fn test_rm_tempdir() {
let (tx, rx) = channel();
- let f = move || -> () {
+ let f = move || {
let tmp = t!(TempDir::new());
tx.send(tmp.path().to_path_buf()).unwrap();
panic!("panic to unwind past `tmp`");
@@ -78,7 +78,7 @@ fn test_rm_tempdir() {
let tmp = t!(TempDir::new());
let path = tmp.path().to_path_buf();
- let f = move || -> () {
+ let f = move || {
let _tmp = tmp;
panic!("panic to unwind past `tmp`");
};
@@ -107,7 +107,7 @@ fn test_rm_tempdir() {
fn test_rm_tempdir_close() {
let (tx, rx) = channel();
- let f = move || -> () {
+ let f = move || {
let tmp = t!(TempDir::new());
tx.send(tmp.path().to_path_buf()).unwrap();
t!(tmp.close());
@@ -119,7 +119,7 @@ fn test_rm_tempdir_close() {
let tmp = t!(TempDir::new());
let path = tmp.path().to_path_buf();
- let f = move || -> () {
+ let f = move || {
let tmp = tmp;
t!(tmp.close());
panic!("panic when unwinding past `tmp`");
diff --git a/vendor/tempfile/tests/tempfile.rs b/vendor/tempfile/tests/tempfile.rs
index f4dddb290..c2f684438 100644
--- a/vendor/tempfile/tests/tempfile.rs
+++ b/vendor/tempfile/tests/tempfile.rs
@@ -2,8 +2,11 @@
use std::fs;
use std::io::{Read, Seek, SeekFrom, Write};
-use std::sync::mpsc::{sync_channel, TryRecvError};
-use std::thread;
+#[cfg(target_os = "linux")]
+use std::{
+ sync::mpsc::{sync_channel, TryRecvError},
+ thread,
+};
#[test]
fn test_basic() {