Revert "Upgrade tempfile to 3.12.0"

This reverts commit f79d9df87f4c32a8f95098db5549c2a1445826d4.

Reason for revert: <Potential culprit for b/366171449  - verifying through ABTD before revert submission. This is part of the standard investigation process, and does not mean your CL will be reverted.>

Change-Id: Iffc8edeebbfaf3599445a5adc35733e316e361d7
diff --git a/crates/tempfile/.cargo-checksum.json b/crates/tempfile/.cargo-checksum.json
new file mode 100644
index 0000000..26f8560
--- /dev/null
+++ b/crates/tempfile/.cargo-checksum.json
@@ -0,0 +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
diff --git a/crates/tempfile/.cargo_vcs_info.json b/crates/tempfile/.cargo_vcs_info.json
deleted file mode 100644
index c9553df..0000000
--- a/crates/tempfile/.cargo_vcs_info.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "git": {
-    "sha1": "5b90d964e42e5eeac225b53e10829c2a4b151b0a"
-  },
-  "path_in_vcs": ""
-}
\ No newline at end of file
diff --git a/crates/tempfile/.github/dependabot.yml b/crates/tempfile/.github/dependabot.yml
deleted file mode 100644
index 98e44ee..0000000
--- a/crates/tempfile/.github/dependabot.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-version: 2
-updates:
-  - package-ecosystem: "cargo"
-    directory: "/"
-    schedule:
-      interval: "weekly"
-  - package-ecosystem: "github-actions"
-    directory: "/"
-    schedule:
-      interval: "weekly"
diff --git a/crates/tempfile/.github/workflows/ci.yml b/crates/tempfile/.github/workflows/ci.yml
deleted file mode 100644
index 9b773d1..0000000
--- a/crates/tempfile/.github/workflows/ci.yml
+++ /dev/null
@@ -1,85 +0,0 @@
-on:
-  push:
-    branches:
-      - master
-  pull_request:
-    branches:
-      - master
-
-name: CI
-jobs:
-  deny:
-    name: Cargo deny
-    strategy:
-      matrix:
-        os:
-          - ubuntu-latest
-    runs-on: ${{ matrix.os }}
-    steps:
-      - uses: actions/checkout@v4
-      - uses: EmbarkStudios/cargo-deny-action@v2
-    timeout-minutes: 10
-
-  build_and_test:
-    name: OS Test
-    strategy:
-      fail-fast: false
-      matrix:
-        rust-version:
-          - nightly
-          - stable
-          - "1.63"
-        os:
-          - ubuntu-latest
-          - windows-latest
-          - macos-latest
-    runs-on: ${{ matrix.os }}
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v4
-      - name: Install Rust
-        uses: dtolnay/rust-toolchain@master
-        with:
-          toolchain: ${{ matrix.rust-version }}
-      - name: Build
-        run: cargo build
-      - name: Test
-        run: cargo test
-  wasi:
-    name: WASI Test Build
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v4
-      - name: Install Rust
-        uses: dtolnay/rust-toolchain@nightly
-      - name: Install Cargo WASI
-        run: cargo install cargo-wasi
-      - name: Build
-        run: cargo wasi build --features nightly
-  wasm:
-    name: WASM Test Build
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v4
-      - name: Install Rust
-        uses: dtolnay/rust-toolchain@stable
-        with:
-          targets: wasm32-unknown-unknown
-      - name: Build
-        run: cargo build --target wasm32-unknown-unknown
-  lint:
-    name: Clippy and fmt
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v4
-      - name: Install Rust
-        uses: dtolnay/rust-toolchain@stable
-        with:
-          components: clippy, rustfmt
-      - name: Check formatting
-        run: cargo fmt --check
-      - name: Check for clippy lints
-        run: cargo clippy
diff --git a/crates/tempfile/.gitignore b/crates/tempfile/.gitignore
deleted file mode 100644
index a9d37c5..0000000
--- a/crates/tempfile/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-target
-Cargo.lock
diff --git a/crates/tempfile/Android.bp b/crates/tempfile/Android.bp
index bd1302b..9f141a9 100644
--- a/crates/tempfile/Android.bp
+++ b/crates/tempfile/Android.bp
@@ -18,14 +18,14 @@
     host_supported: true,
     crate_name: "tempfile",
     cargo_env_compat: true,
-    cargo_pkg_version: "3.12.0",
+    cargo_pkg_version: "3.3.0",
     crate_root: "src/lib.rs",
-    edition: "2021",
+    edition: "2018",
     rustlibs: [
         "libcfg_if",
         "libfastrand",
-        "libonce_cell",
-        "librustix",
+        "liblibc",
+        "libremove_dir_all",
     ],
     apex_available: [
         "//apex_available:anyapex",
@@ -33,5 +33,5 @@
     ],
     product_available: true,
     vendor_available: true,
-    min_sdk_version: "30",
+    min_sdk_version: "29",
 }
diff --git a/crates/tempfile/CHANGELOG.md b/crates/tempfile/CHANGELOG.md
deleted file mode 100644
index 7a43eae..0000000
--- a/crates/tempfile/CHANGELOG.md
+++ /dev/null
@@ -1,290 +0,0 @@
-# Changelog
-
-## 3.12.0
-
-- Add a `keep(keep: bool)` function to builder that suppresses delete-on-drop behavior (thanks to @RalfJung).
-- Update `windows-sys` from 0.52 to 0.59.
-
-## 3.11.0
-
-- Add the ability to override the default temporary directory. This API shouldn't be used in general, but there are some cases where it's unavoidable.
-
-## 3.10.1
-
-- Handle potential integer overflows in 32-bit systems when seeking/truncating "spooled" temporary files past 4GiB (2³²).
-- Handle a theoretical 32-bit overflow when generating a temporary file name larger than 4GiB. Now it'll panic (on allocation failure) rather than silently succeeding due to wraparound.
-
-Thanks to @stoeckmann for finding and fixing both of these issues.
-
-## 3.10.0
-
-- Drop `redox_syscall` dependency, we now use `rustix` for Redox.
-- Add `Builder::permissions` for setting the permissions on temporary files and directories (thanks to @Byron).
-- Update rustix to 0.38.31.
-- Update fastrand to 2.0.1.
-
-## 3.9.0
-
-- Updates windows-sys to 0.52
-- Updates minimum rustix version to 0.38.25
-
-## 3.8.1
-
-- Update rustix to fix a potential panic on `persist_noclobber` on android.
-- Update redox_syscall to 0.4 (on redox).
-- Fix some docs typos.
-
-## 3.8.0
-
-- Added `with_prefix` and `with_prefix_in` to `TempDir` and `NamedTempFile` to make it easier to create temporary files/directories with nice prefixes.
-- Misc cleanups.
-
-## 3.7.1
-
-- Tempfile builds on haiku again.
-- Under the hood, we've switched from the unlinkat/linkat syscalls to the regular unlink/link syscalls where possible.
-
-## 3.7.0
-
-BREAKING: This release updates the MSRV to 1.63. This isn't an API-breaking change (so no major
-release) but it's still a breaking change for some users.
-
-- Update fastrand from 1.6 to 2.0
-- Update rustix to 0.38
-- Updates the MSRV to 1.63.
-- Provide AsFd/AsRawFd on wasi.
-
-## 3.6.0
-
-- Update windows-sys to 0.48.
-- Update rustix min version to 0.37.11
-- Forward some `NamedTempFile` and `SpooledTempFile` methods to the underlying `File` object for
-  better performance (especially vectorized writes, etc.).
-- Implement `AsFd` and `AsHandle`.
-- Misc documentation fixes and code cleanups.
-
-## 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
-
-Features:
-
-- Replace rand with fastrand for a significantly smaller dependency tree. Cryptographic randomness
-  isn't necessary for temporary file names, and isn't all that helpful either.
-- Add limited WASI support.
-- Add a function to extract the inner data from a `SpooledTempFile`.
-
-Bug Fixes:
-
-- Make it possible to persist unnamed temporary files on linux by removing the `O_EXCL` flag.
-- Fix redox minimum crate version.
-
-## 3.2.0
-
-Features:
-
-- Bump rand dependency to `0.8`.
-- Bump cfg-if dependency to `1.0`
-
-Other than that, this release mostly includes small cleanups and simplifications.
-
-Breaking: The minimum rust version is now `1.40.0`.
-
-## 3.1.0
-
-Features:
-
-- Bump rand dependency to `0.7`.
-
-Breaking: The minimum rust version is now `1.32.0`.
-
-## 3.0.9
-
-Documentation:
-
-- Add an example for reopening a named temporary file.
-- Flesh out the security documentation.
-
-Features:
-
-- Introduce an `append` option to the builder.
-- Errors:
-  - No longer implement the soft-deprecated `description`.
-  - Implement `source` instead of `cause`.
-
-Breaking: The minimum rust version is now 1.30.
-
-## 3.0.8
-
-This is a bugfix release.
-
-Fixes:
-
-- Export `PathPersistError`.
-- Fix a bug where flushing a `SpooledTempFile` to disk could fail to write part
-  of the file in some rare, yet-to-reproduced cases.
-
-## 3.0.7
-
-Breaking:
-
-- `Builder::prefix` and `Builder::suffix` now accept a generic `&AsRef<OsStr>`.
-  This could affect type inference.
-- Temporary files (except unnamed temporary files on Windows and Linux >= 3.11)
-  now use absolute path names. This will break programs that create temporary
-  files relative to their current working directory when they don't have the
-  search permission (x) on some ancestor directory. This is only likely to
-  affect programs with strange chroot-less filesystem sandboxes. If you believe
-  you're affected by this issue, please comment on #40.
-
-Features:
-
-- Accept anything implementing `&AsRef<OsStr>` in the builder: &OsStr, &OsString, &Path, etc.
-
-Fixes:
-
-- Fix LFS support.
-- Use absolute paths for named temporary files to guard against changes in the
-  current directory.
-- Use absolute paths when creating unnamed temporary files on platforms that
-  can't create unlinked or auto-deleted temporary files. This fixes a very
-  unlikely race where the current directory could change while the temporary
-  file is being created.
-
-Misc:
-
-- Use modern stdlib features to avoid custom unsafe code. This reduces the
-  number of unsafe blocks from 12 to 4.
-
-## 3.0.6
-
-- Don't hide temporary files on windows, fixing #66 and #69.
-
-## 3.0.5
-
-Features:
-
-- Added a spooled temporary file implementation. This temporary file variant
-  starts out as an in-memory temporary file but "rolls-over" onto disk when it
-  grows over a specified size (#68).
-- Errors are now annotated with paths to make debugging easier (#73).
-
-Misc:
-
-- The rand version has been bumped to 0.6 (#74).
-
-Bugs:
-
-- Tempfile compiles again on Redox (#75).
-
-## 3.0.4
-
-- Now compiles on unsupported platforms.
-
-## 3.0.3
-
-- update rand to 0.5
-
-## 3.0.2
-
-- Actually *delete* temporary files on non-Linux unix systems (thanks to
-@oliverhenshaw for the fix and a test case).
-
-## 3.0.1
-
-- Restore NamedTempFile::new_in
-
-## 3.0.0
-
-- Adds temporary directory support (@KodrAus)
-- Allow closing named temporary files without deleting them (@jasonwhite)
-
-## 2.2.0
-
-- Redox Support
-
-## 2.1.6
-
-- Remove build script and bump minimum rustc version to 1.9.0
-
-## 2.1.5
-
-- Don't build platform-specific dependencies on all platforms.
-- Cleanup some documentation.
-
-## 2.1.4
-
-- Fix crates.io tags. No interesting changes.
-
-## 2.1.3
-
-Export `PersistError`.
-
-## 2.1.2
-
-Add `Read`/`Write`/`Seek` impls on `&NamedTempFile`. This mirrors the
-implementations on `&File`. One can currently just deref to a `&File` but these
-implementations are more discoverable.
-
-## 2.1.1
-
-Add LFS Support.
-
-## 2.1.0
-
-- Implement `AsRef<File>` for `NamedTempFile` allowing named temporary files to
-  be borrowed as `File`s.
-- Add a method to convert a `NamedTempFile` to an unnamed temporary `File`.
-
-## 2.0.1
-
-- Arm bugfix
-
-## 2.0.0
-
-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.
-
-To continue supporting shared temporary files, this new version adds a
-`reopen()` method to `NamedTempFile`.
diff --git a/crates/tempfile/Cargo.toml b/crates/tempfile/Cargo.toml
index a199caa..253f866 100644
--- a/crates/tempfile/Cargo.toml
+++ b/crates/tempfile/Cargo.toml
@@ -10,81 +10,34 @@
 # See Cargo.toml.orig for the original contents.
 
 [package]
-edition = "2021"
-rust-version = "1.63"
+edition = "2018"
 name = "tempfile"
-version = "3.12.0"
-authors = [
-    "Steven Allen <steven@stebalien.com>",
-    "The Rust Project Developers",
-    "Ashley Mannix <ashleymannix@live.com.au>",
-    "Jason White <me@jasonwhite.io>",
-]
-build = false
-autobins = false
-autoexamples = false
-autotests = false
-autobenches = false
+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"]
 description = "A library for managing temporary files and directories."
-homepage = "https://stebalien.com/projects/tempfile-rs/"
+homepage = "http://stebalien.com/projects/tempfile-rs"
 documentation = "https://docs.rs/tempfile"
-readme = "README.md"
-keywords = [
-    "tempfile",
-    "tmpfile",
-    "filesystem",
-]
+keywords = ["tempfile", "tmpfile", "filesystem"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/Stebalien/tempfile"
-
-[lib]
-name = "tempfile"
-path = "src/lib.rs"
-
-[[test]]
-name = "env"
-path = "tests/env.rs"
-
-[[test]]
-name = "namedtempfile"
-path = "tests/namedtempfile.rs"
-
-[[test]]
-name = "spooled"
-path = "tests/spooled.rs"
-
-[[test]]
-name = "tempdir"
-path = "tests/tempdir.rs"
-
-[[test]]
-name = "tempfile"
-path = "tests/tempfile.rs"
-
 [dependencies.cfg-if]
 version = "1"
 
 [dependencies.fastrand]
-version = "2.0.1"
+version = "1.6.0"
 
-[dependencies.once_cell]
-version = "1.19.0"
-features = ["std"]
-default-features = false
-
+[dependencies.remove_dir_all]
+version = "0.5"
 [dev-dependencies.doc-comment]
 version = "0.3"
 
 [features]
 nightly = []
-
-[target.'cfg(any(unix, target_os = "wasi"))'.dependencies.rustix]
-version = "0.38.31"
-features = ["fs"]
-
-[target."cfg(windows)".dependencies.windows-sys]
-version = "0.59"
-features = [
-    "Win32_Storage_FileSystem",
-    "Win32_Foundation",
-]
+[target."cfg(any(unix, target_os = \"wasi\"))".dependencies.libc]
+version = "0.2.27"
+[target."cfg(target_os = \"redox\")".dependencies.redox_syscall]
+version = "0.2.9"
+[target."cfg(windows)".dependencies.winapi]
+version = "0.3"
+features = ["fileapi", "handleapi", "winbase"]
diff --git a/crates/tempfile/Cargo.toml.orig b/crates/tempfile/Cargo.toml.orig
deleted file mode 100644
index 1dee2d9..0000000
--- a/crates/tempfile/Cargo.toml.orig
+++ /dev/null
@@ -1,39 +0,0 @@
-[package]
-name = "tempfile"
-version = "3.12.0"
-authors = [
-  "Steven Allen <steven@stebalien.com>",
-  "The Rust Project Developers",
-  "Ashley Mannix <ashleymannix@live.com.au>",
-  "Jason White <me@jasonwhite.io>",
-]
-documentation = "https://docs.rs/tempfile"
-edition = "2021"
-rust-version = "1.63"
-homepage = "https://stebalien.com/projects/tempfile-rs/"
-keywords = ["tempfile", "tmpfile", "filesystem"]
-license = "MIT OR Apache-2.0"
-repository = "https://github.com/Stebalien/tempfile"
-description = "A library for managing temporary files and directories."
-
-[dependencies]
-cfg-if = "1"
-fastrand = "2.0.1"
-# Not available in stdlib until 1.70, but we support 1.63 to support Debian stable.
-once_cell = { version = "1.19.0", default-features = false, features = ["std"] }
-
-[target.'cfg(any(unix, target_os = "wasi"))'.dependencies]
-rustix = { version = "0.38.31", features = ["fs"] }
-
-[target.'cfg(windows)'.dependencies.windows-sys]
-version = "0.59"
-features = [
-    "Win32_Storage_FileSystem",
-    "Win32_Foundation",
-]
-
-[dev-dependencies]
-doc-comment = "0.3"
-
-[features]
-nightly = []
diff --git a/crates/tempfile/METADATA b/crates/tempfile/METADATA
index daf2b4c..6add873 100644
--- a/crates/tempfile/METADATA
+++ b/crates/tempfile/METADATA
@@ -1,17 +1,17 @@
 name: "tempfile"
 description: "A library for managing temporary files and directories."
 third_party {
-  version: "3.12.0"
+  version: "3.3.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2024
-    month: 9
+    year: 2023
+    month: 2
     day: 6
   }
   homepage: "https://crates.io/crates/tempfile"
   identifier {
     type: "Archive"
-    value: "https://static.crates.io/crates/tempfile/tempfile-3.12.0.crate"
-    version: "3.12.0"
+    value: "https://static.crates.io/crates/tempfile/tempfile-3.3.0.crate"
+    version: "3.3.0"
   }
 }
diff --git a/crates/tempfile/NEWS b/crates/tempfile/NEWS
new file mode 100644
index 0000000..c284424
--- /dev/null
+++ b/crates/tempfile/NEWS
@@ -0,0 +1,206 @@
+3.3.0
+=====
+
+Features:
+
+* Replace rand with fastrand for a significantly smaller dependency tree. Cryptographic randomness
+  isn't necessary for temporary file names, and isn't all that helpful either.
+* Add limited WASI support.
+* Add a function to extract the inner data from a `SpooledTempFile`.
+
+Bug Fixes:
+
+* Make it possible to persist unnamed temporary files on linux by removing the `O_EXCL` flag.
+* Fix redox minimum crate version.
+
+3.2.0
+=====
+
+Features:
+
+* Bump rand dependency to `0.8`.
+* Bump cfg-if dependency to `1.0`
+
+Other than that, this release mostly includes small cleanups and simplifications.
+
+Breaking: The minimum rust version is now `1.40.0`.
+
+3.1.0
+=====
+
+Features:
+
+* Bump rand dependency to `0.7`.
+
+Breaking: The minimum rust version is now `1.32.0`.
+
+3.0.9
+=====
+
+Documentation:
+
+* Add an example for reopening a named temporary file.
+* Flesh out the security documentation.
+
+Features:
+
+* Introduce an `append` option to the builder.
+* Errors:
+  * No longer implement the soft-deprecated `description`.
+  * Implement `source` instead of `cause`.
+
+Breaking: The minimum rust version is now 1.30.
+
+3.0.8
+=====
+
+This is a bugfix release.
+
+Fixes:
+
+* Export `PathPersistError`.
+* Fix a bug where flushing a `SpooledTempFile` to disk could fail to write part
+  of the file in some rare, yet-to-reproduced cases.
+
+3.0.7
+=====
+
+Breaking:
+
+* `Builder::prefix` and `Builder::suffix` now accept a generic `&AsRef<OsStr>`.
+  This could affect type inference.
+* Temporary files (except unnamed temporary files on Windows and Linux >= 3.11)
+  now use absolute path names. This will break programs that create temporary
+  files relative to their current working directory when they don't have the
+  search permission (x) on some ancestor directory. This is only likely to
+  affect programs with strange chroot-less filesystem sandboxes. If you believe
+  you're affected by this issue, please comment on #40.
+
+Features:
+
+* Accept anything implementing `&AsRef<OsStr>` in the builder: &OsStr, &OsString, &Path, etc.
+
+Fixes:
+
+* Fix LFS support.
+* Use absolute paths for named temporary files to guard against changes in the
+  current directory.
+* Use absolute paths when creating unnamed temporary files on platforms that
+  can't create unlinked or auto-deleted temporary files. This fixes a very
+  unlikely race where the current directory could change while the temporary
+  file is being created.
+
+Misc:
+
+* Use modern stdlib features to avoid custom unsafe code. This reduces the
+  number of unsafe blocks from 12 to 4.
+
+3.0.6
+=====
+
+* Don't hide temporary files on windows, fixing #66 and #69.
+
+3.0.5
+=====
+
+Features:
+
+* Added a spooled temporary file implementation. This temporary file variant
+  starts out as an in-memory temporary file but "rolls-over" onto disk when it
+  grows over a specified size (#68).
+* Errors are now annotated with paths to make debugging easier (#73).
+
+Misc:
+
+* The rand version has been bumped to 0.6 (#74).
+
+Bugs:
+
+* Tempfile compiles again on Redox (#75).
+
+3.0.4
+=====
+
+* Now compiles on unsupported platforms.
+
+3.0.3
+=====
+
+* update rand to 0.5
+
+3.0.2
+=====
+
+* Actually *delete* temporary files on non-Linux unix systems (thanks to
+@oliverhenshaw for the fix and a test case).
+
+3.0.1
+=====
+
+* Restore NamedTempFile::new_in
+
+3.0.0
+=====
+
+* Adds temporary directory support (@KodrAus)
+* Allow closing named temporary files without deleting them (@jasonwhite)
+
+2.2.0
+=====
+
+* Redox Support
+
+2.1.6
+=====
+
+* Remove build script and bump minimum rustc version to 1.9.0
+
+2.1.5
+=====
+
+* Don't build platform-specific dependencies on all platforms.
+* Cleanup some documentation.
+
+2.1.4
+=====
+
+* Fix crates.io tags. No interesting changes.
+
+2.1.3
+=====
+
+Export `PersistError`.
+
+2.1.2
+=====
+
+Add `Read`/`Write`/`Seek` impls on `&NamedTempFile`. This mirrors the
+implementations on `&File`. One can currently just deref to a `&File` but these
+implementations are more discoverable.
+
+2.1.1
+=====
+
+Add LFS Support.
+
+2.1.0
+=====
+
+* Implement `AsRef<File>` for `NamedTempFile` allowing named temporary files to
+  be borrowed as `File`s.
+* Add a method to convert a `NamedTempFile` to an unnamed temporary `File`.
+
+2.0.1
+=====
+
+* Arm bugfix
+
+2.0.0
+=====
+
+This release replaces `TempFile` with a `tempfile()` function that returnes
+`std::fs::File` objects. These are significantly more useful because most rust
+libraries expect normal `File` objects.
+
+To continue supporting shared temporary files, this new version adds a
+`reopen()` method to `NamedTempFile`.
diff --git a/crates/tempfile/README.md b/crates/tempfile/README.md
index 4d886b1..1dba3a0 100644
--- a/crates/tempfile/README.md
+++ b/crates/tempfile/README.md
@@ -14,10 +14,9 @@
 Usage
 -----
 
-Minimum required Rust version: 1.63.0
+Minimum required Rust version: 1.40.0
 
 Add this to your `Cargo.toml`:
-
 ```toml
 [dependencies]
 tempfile = "3"
diff --git a/crates/tempfile/cargo_embargo.json b/crates/tempfile/cargo_embargo.json
index cd6c19e..3e8023e 100644
--- a/crates/tempfile/cargo_embargo.json
+++ b/crates/tempfile/cargo_embargo.json
@@ -3,6 +3,6 @@
     "//apex_available:anyapex",
     "//apex_available:platform"
   ],
-  "min_sdk_version": "30",
+  "min_sdk_version": "29",
   "run_cargo": false
 }
diff --git a/crates/tempfile/deny.toml b/crates/tempfile/deny.toml
deleted file mode 100644
index a2cf7ed..0000000
--- a/crates/tempfile/deny.toml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-[advisories]
-yanked = "deny"
-ignore = []
-
-[licenses]
-allow = [
-    "Apache-2.0",
-    "MIT",
-]
-confidence-threshold = 1.0
-
-[bans]
-allow = []
-deny = []
-multiple-versions = "deny"
-skip = [
-    # Dependency of this crate and and rustix (rustix has older). We only use one at a time.
-    { name = "windows-sys" },
-]
-skip-tree = []
-wildcards = "deny"
-
-[sources]
-allow-git = []
-allow-registry = ["https://github.com/rust-lang/crates.io-index"]
-unknown-git = "deny"
-unknown-registry = "deny"
-
-[sources.allow-org]
-github = []
-gitlab = []
-bitbucket = []
diff --git a/crates/tempfile/src/dir/mod.rs b/crates/tempfile/src/dir.rs
similarity index 73%
rename from crates/tempfile/src/dir/mod.rs
rename to crates/tempfile/src/dir.rs
index 067c74a..d5a944b 100644
--- a/crates/tempfile/src/dir/mod.rs
+++ b/crates/tempfile/src/dir.rs
@@ -8,18 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::ffi::OsStr;
-use std::fs::remove_dir_all;
+use remove_dir_all::remove_dir_all;
 use std::mem;
 use std::path::{self, Path, PathBuf};
-use std::{fmt, io};
+use std::{fmt, fs, io};
 
 use crate::error::IoResultExt;
 use crate::Builder;
 
-#[cfg(doc)]
-use crate::env;
-
 /// Create a new temporary directory.
 ///
 /// The `tempdir` function creates a directory in the file system
@@ -40,20 +36,27 @@
 /// ```
 /// use tempfile::tempdir;
 /// use std::fs::File;
-/// use std::io::Write;
+/// use std::io::{self, Write};
 ///
-/// // Create a directory inside of `env::temp_dir()`
-/// let tmp_dir = tempdir()?;
+/// # 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 = tmp_dir.path().join("my-temporary-note.txt");
-/// let mut tmp_file = File::create(file_path)?;
-/// writeln!(tmp_file, "Brian was here. Briefly.")?;
+/// let file_path = dir.path().join("my-temporary-note.txt");
+/// let mut file = File::create(file_path)?;
+/// writeln!(file, "Brian was here. Briefly.")?;
 ///
 /// // `tmp_dir` goes out of scope, the directory as well as
 /// // `tmp_file` will be deleted here.
-/// drop(tmp_file);
-/// tmp_dir.close()?;
-/// # Ok::<(), std::io::Error>(())
+/// drop(file);
+/// dir.close()?;
+/// # Ok(())
+/// # }
 /// ```
 ///
 /// [`TempDir`]: struct.TempDir.html
@@ -62,9 +65,9 @@
     TempDir::new()
 }
 
-/// Create a new temporary directory in a specific directory.
+/// Create a new temporary directory.
 ///
-/// The `tempdir_in` function creates a directory in the specified directory
+/// The `tempdir` function creates a directory in the file system
 /// and returns a [`TempDir`].
 /// The directory will be automatically deleted when the `TempDir`s
 /// destructor is run.
@@ -80,22 +83,29 @@
 /// # Examples
 ///
 /// ```
-/// use tempfile::tempdir_in;
+/// use tempfile::tempdir;
 /// use std::fs::File;
-/// use std::io::Write;
+/// use std::io::{self, Write};
 ///
-/// // Create a directory inside of the current directory.
-/// let tmp_dir = tempdir_in(".")?;
+/// # 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 = tmp_dir.path().join("my-temporary-note.txt");
-/// let mut tmp_file = File::create(file_path)?;
-/// writeln!(tmp_file, "Brian was here. Briefly.")?;
+/// let file_path = dir.path().join("my-temporary-note.txt");
+/// let mut file = File::create(file_path)?;
+/// writeln!(file, "Brian was here. Briefly.")?;
 ///
 /// // `tmp_dir` goes out of scope, the directory as well as
 /// // `tmp_file` will be deleted here.
-/// drop(tmp_file);
-/// tmp_dir.close()?;
-/// # Ok::<(), std::io::Error>(())
+/// drop(file);
+/// dir.close()?;
+/// # Ok(())
+/// # }
 /// ```
 ///
 /// [`TempDir`]: struct.TempDir.html
@@ -112,7 +122,7 @@
 /// `TempDir` creates a new directory with a randomly generated name.
 ///
 /// The default constructor, [`TempDir::new()`], creates directories in
-/// the location returned by [`env::temp_dir()`], but `TempDir`
+/// the location returned by [`std::env::temp_dir()`], but `TempDir`
 /// can be configured to manage a temporary directory in any location
 /// by constructing with a [`Builder`].
 ///
@@ -147,9 +157,12 @@
 /// use std::io::Write;
 /// use tempfile::TempDir;
 ///
-/// // Create a directory inside of `env::temp_dir()`
+/// # use std::io;
+/// # fn run() -> Result<(), io::Error> {
+/// // Create a directory inside of `std::env::temp_dir()`
 /// let tmp_dir = TempDir::new()?;
-/// # Ok::<(), std::io::Error>(())
+/// # Ok(())
+/// # }
 /// ```
 ///
 /// Create a temporary directory with a prefix in its name:
@@ -159,10 +172,13 @@
 /// use std::io::Write;
 /// use tempfile::Builder;
 ///
-/// // Create a directory inside of `env::temp_dir()`,
+/// # use std::io;
+/// # fn run() -> Result<(), io::Error> {
+/// // Create a directory inside of `std::env::temp_dir()`,
 /// // whose name will begin with 'example'.
 /// let tmp_dir = Builder::new().prefix("example").tempdir()?;
-/// # Ok::<(), std::io::Error>(())
+/// # Ok(())
+/// # }
 /// ```
 ///
 /// [`File`]: http://doc.rust-lang.org/std/fs/struct.File.html
@@ -173,11 +189,11 @@
 /// [`TempDir::new()`]: struct.TempDir.html#method.new
 /// [`TempDir::path()`]: struct.TempDir.html#method.path
 /// [`TempDir`]: struct.TempDir.html
+/// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
 /// [`std::fs`]: http://doc.rust-lang.org/std/fs/index.html
 /// [`std::process::exit()`]: http://doc.rust-lang.org/std/process/fn.exit.html
 pub struct TempDir {
     path: Box<Path>,
-    keep: bool,
 }
 
 impl TempDir {
@@ -199,7 +215,9 @@
     /// use std::io::Write;
     /// use tempfile::TempDir;
     ///
-    /// // Create a directory inside of `env::temp_dir()`
+    /// # use std::io;
+    /// # fn run() -> Result<(), io::Error> {
+    /// // Create a directory inside of `std::env::temp_dir()`
     /// let tmp_dir = TempDir::new()?;
     ///
     /// let file_path = tmp_dir.path().join("my-temporary-note.txt");
@@ -208,7 +226,8 @@
     ///
     /// // `tmp_dir` goes out of scope, the directory as well as
     /// // `tmp_file` will be deleted here.
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// [`Builder`]: struct.Builder.html
@@ -231,70 +250,20 @@
     /// use std::io::Write;
     /// use tempfile::TempDir;
     ///
+    /// # use std::io;
+    /// # fn run() -> Result<(), io::Error> {
     /// // Create a directory inside of the current directory
     /// let tmp_dir = TempDir::new_in(".")?;
     /// let file_path = tmp_dir.path().join("my-temporary-note.txt");
     /// let mut tmp_file = File::create(file_path)?;
     /// writeln!(tmp_file, "Brian was here. Briefly.")?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<TempDir> {
         Builder::new().tempdir_in(dir)
     }
 
-    /// Attempts to make a temporary directory with the specified prefix inside of
-    /// `env::temp_dir()`. The directory and everything inside it will be automatically
-    /// deleted once the returned `TempDir` is destroyed.
-    ///
-    /// # Errors
-    ///
-    /// If the directory can not be created, `Err` is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::fs::{self, File};
-    /// use std::io::Write;
-    /// use tempfile::TempDir;
-    ///
-    /// // Create a directory inside of the current directory
-    /// let tmp_dir = TempDir::with_prefix("foo-")?;
-    /// let tmp_name = tmp_dir.path().file_name().unwrap().to_str().unwrap();
-    /// assert!(tmp_name.starts_with("foo-"));
-    /// # Ok::<(), std::io::Error>(())
-    /// ```
-    pub fn with_prefix<S: AsRef<OsStr>>(prefix: S) -> io::Result<TempDir> {
-        Builder::new().prefix(&prefix).tempdir()
-    }
-
-    /// Attempts to make a temporary directory with the specified prefix inside
-    /// the specified directory. The directory and everything inside it will be
-    /// automatically deleted once the returned `TempDir` is destroyed.
-    ///
-    /// # Errors
-    ///
-    /// If the directory can not be created, `Err` is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::fs::{self, File};
-    /// use std::io::Write;
-    /// use tempfile::TempDir;
-    ///
-    /// // Create a directory inside of the current directory
-    /// let tmp_dir = TempDir::with_prefix_in("foo-", ".")?;
-    /// let tmp_name = tmp_dir.path().file_name().unwrap().to_str().unwrap();
-    /// assert!(tmp_name.starts_with("foo-"));
-    /// # Ok::<(), std::io::Error>(())
-    /// ```
-    pub fn with_prefix_in<S: AsRef<OsStr>, P: AsRef<Path>>(
-        prefix: S,
-        dir: P,
-    ) -> io::Result<TempDir> {
-        Builder::new().prefix(&prefix).tempdir_in(dir)
-    }
-
     /// Accesses the [`Path`] to the temporary directory.
     ///
     /// [`Path`]: http://doc.rust-lang.org/std/path/struct.Path.html
@@ -304,6 +273,8 @@
     /// ```
     /// use tempfile::TempDir;
     ///
+    /// # use std::io;
+    /// # fn run() -> Result<(), io::Error> {
     /// let tmp_path;
     ///
     /// {
@@ -318,9 +289,9 @@
     ///
     /// // Temp directory should be deleted by now
     /// assert_eq!(tmp_path.exists(), false);
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
-    #[must_use]
     pub fn path(&self) -> &path::Path {
         self.path.as_ref()
     }
@@ -339,6 +310,8 @@
     /// use std::fs;
     /// use tempfile::TempDir;
     ///
+    /// # use std::io;
+    /// # fn run() -> Result<(), io::Error> {
     /// let tmp_dir = TempDir::new()?;
     ///
     /// // Persist the temporary directory to disk,
@@ -347,9 +320,9 @@
     ///
     /// // Delete the temporary directory ourselves.
     /// fs::remove_dir_all(tmp_path)?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
-    #[must_use]
     pub fn into_path(self) -> PathBuf {
         // Prevent the Drop impl from being called.
         let mut this = mem::ManuallyDrop::new(self);
@@ -381,7 +354,9 @@
     /// use std::io::Write;
     /// use tempfile::TempDir;
     ///
-    /// // Create a directory inside of `env::temp_dir()`.
+    /// # use std::io;
+    /// # fn run() -> Result<(), io::Error> {
+    /// // Create a directory inside of `std::env::temp_dir()`.
     /// let tmp_dir = TempDir::new()?;
     /// let file_path = tmp_dir.path().join("my-temporary-note.txt");
     /// let mut tmp_file = File::create(file_path)?;
@@ -394,7 +369,8 @@
     /// // succeeded.
     /// drop(tmp_file);
     /// tmp_dir.close()?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     pub fn close(mut self) -> io::Result<()> {
         let result = remove_dir_all(self.path()).with_err_path(|| self.path());
@@ -426,18 +402,14 @@
 
 impl Drop for TempDir {
     fn drop(&mut self) {
-        if !self.keep {
-            let _ = remove_dir_all(self.path());
-        }
+        let _ = remove_dir_all(self.path());
     }
 }
 
-pub(crate) fn create(
-    path: PathBuf,
-    permissions: Option<&std::fs::Permissions>,
-    keep: bool,
-) -> io::Result<TempDir> {
-    imp::create(path, permissions, keep)
+pub(crate) fn create(path: PathBuf) -> io::Result<TempDir> {
+    fs::create_dir(&path)
+        .with_err_path(|| &path)
+        .map(|_| TempDir {
+            path: path.into_boxed_path(),
+        })
 }
-
-mod imp;
diff --git a/crates/tempfile/src/dir/imp/any.rs b/crates/tempfile/src/dir/imp/any.rs
deleted file mode 100644
index 512a54e..0000000
--- a/crates/tempfile/src/dir/imp/any.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-use crate::error::IoResultExt;
-use crate::TempDir;
-use std::path::PathBuf;
-use std::{fs, io};
-
-fn not_supported<T>(msg: &str) -> io::Result<T> {
-    Err(io::Error::new(io::ErrorKind::Other, msg))
-}
-
-pub fn create(
-    path: PathBuf,
-    permissions: Option<&std::fs::Permissions>,
-    keep: bool,
-) -> io::Result<TempDir> {
-    if permissions.map_or(false, |p| p.readonly()) {
-        return not_supported("changing permissions is not supported on this platform");
-    }
-    fs::create_dir(&path)
-        .with_err_path(|| &path)
-        .map(|_| TempDir {
-            path: path.into_boxed_path(),
-            keep,
-        })
-}
diff --git a/crates/tempfile/src/dir/imp/mod.rs b/crates/tempfile/src/dir/imp/mod.rs
deleted file mode 100644
index 26d0a22..0000000
--- a/crates/tempfile/src/dir/imp/mod.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#[cfg(unix)]
-mod unix;
-#[cfg(unix)]
-pub use unix::*;
-
-#[cfg(not(unix))]
-mod any;
-#[cfg(not(unix))]
-pub use any::*;
diff --git a/crates/tempfile/src/dir/imp/unix.rs b/crates/tempfile/src/dir/imp/unix.rs
deleted file mode 100644
index d69dac3..0000000
--- a/crates/tempfile/src/dir/imp/unix.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-use crate::error::IoResultExt;
-use crate::TempDir;
-use std::io;
-use std::path::PathBuf;
-
-pub fn create(
-    path: PathBuf,
-    permissions: Option<&std::fs::Permissions>,
-    keep: bool,
-) -> io::Result<TempDir> {
-    let mut dir_options = std::fs::DirBuilder::new();
-    #[cfg(not(target_os = "wasi"))]
-    {
-        use std::os::unix::fs::{DirBuilderExt, PermissionsExt};
-        if let Some(p) = permissions {
-            dir_options.mode(p.mode());
-        }
-    }
-    dir_options
-        .create(&path)
-        .with_err_path(|| &path)
-        .map(|_| TempDir {
-            path: path.into_boxed_path(),
-            keep,
-        })
-}
diff --git a/crates/tempfile/src/env.rs b/crates/tempfile/src/env.rs
deleted file mode 100644
index 86d5199..0000000
--- a/crates/tempfile/src/env.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use std::env;
-use std::path::{Path, PathBuf};
-
-// Once rust 1.70 is wide-spread (Debian stable), we can use OnceLock from stdlib.
-use once_cell::sync::OnceCell as OnceLock;
-
-static DEFAULT_TEMPDIR: OnceLock<PathBuf> = OnceLock::new();
-
-/// Override the default temporary directory (defaults to [`std::env::temp_dir`]). This function
-/// changes the _global_ default temporary directory for the entire program and should not be called
-/// except in exceptional cases where it's not configured correctly by the platform.
-///
-/// Only the first call to this function will succeed. All further calls will fail with `Err(path)`
-/// where `path` is previously set default temporary directory override.
-///
-/// **NOTE:** This function does not check if the specified directory exists and/or is writable.
-pub fn override_temp_dir(path: &Path) -> Result<(), PathBuf> {
-    let mut we_set = false;
-    let val = DEFAULT_TEMPDIR.get_or_init(|| {
-        we_set = true;
-        path.to_path_buf()
-    });
-    if we_set {
-        Ok(())
-    } else {
-        Err(val.to_owned())
-    }
-}
-
-/// Returns the default temporary directory, used for both temporary directories and files if no
-/// directory is explicitly specified.
-///
-/// This function simply delegates to [`std::env::temp_dir`] unless the default temporary directory
-/// has been override by a call to [`override_temp_dir`].
-///
-/// **NOTE:** This function does check if the returned directory exists and/or is writable.
-pub fn temp_dir() -> PathBuf {
-    DEFAULT_TEMPDIR
-        .get()
-        .map(|p| p.to_owned())
-        // Don't cache this in case the user uses std::env::set to change the temporary directory.
-        .unwrap_or_else(env::temp_dir)
-}
diff --git a/crates/tempfile/src/file/imp/other.rs b/crates/tempfile/src/file/imp/other.rs
index bba3671..d8a55a7 100644
--- a/crates/tempfile/src/file/imp/other.rs
+++ b/crates/tempfile/src/file/imp/other.rs
@@ -9,11 +9,7 @@
     ))
 }
 
-pub fn create_named(
-    _path: &Path,
-    _open_options: &mut OpenOptions,
-    _permissions: Option<&std::fs::Permissions>,
-) -> io::Result<File> {
+pub fn create_named(_path: &Path, open_options: &mut OpenOptions) -> io::Result<File> {
     not_supported()
 }
 
@@ -29,6 +25,6 @@
     not_supported()
 }
 
-pub fn keep(_path: &Path) -> io::Result<()> {
+pub fn keep(path: &Path) -> io::Result<()> {
     not_supported()
 }
diff --git a/crates/tempfile/src/file/imp/unix.rs b/crates/tempfile/src/file/imp/unix.rs
index 117d76a..480743c 100644
--- a/crates/tempfile/src/file/imp/unix.rs
+++ b/crates/tempfile/src/file/imp/unix.rs
@@ -1,10 +1,13 @@
-use std::ffi::OsStr;
+use std::env;
+use std::ffi::{CString, OsStr};
 use std::fs::{self, File, OpenOptions};
 use std::io;
 cfg_if::cfg_if! {
     if #[cfg(not(target_os = "wasi"))] {
-        use std::os::unix::fs::MetadataExt;
+        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;
     }
@@ -13,22 +16,36 @@
 use std::path::Path;
 
 #[cfg(not(target_os = "redox"))]
-use {
-    rustix::fs::{rename, unlink},
-    std::fs::hard_link,
-};
+use libc::{c_char, c_int, link, rename, unlink};
 
-pub fn create_named(
-    path: &Path,
-    open_options: &mut OpenOptions,
-    #[cfg_attr(target_os = "wasi", allow(unused))] permissions: Option<&std::fs::Permissions>,
-) -> io::Result<File> {
+#[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"))
+}
+
+pub fn create_named(path: &Path, open_options: &mut OpenOptions) -> io::Result<File> {
     open_options.read(true).write(true).create_new(true);
 
     #[cfg(not(target_os = "wasi"))]
     {
-        use std::os::unix::fs::{OpenOptionsExt, PermissionsExt};
-        open_options.mode(permissions.map(|p| p.mode()).unwrap_or(0o600));
+        open_options.mode(0o600);
     }
 
     open_options.open(path)
@@ -39,12 +56,12 @@
     // shadow this to decrease the lifetime. It can't live longer than `tmp`.
     let mut path = path;
     if !path.is_absolute() {
-        let cur_dir = std::env::current_dir()?;
+        let cur_dir = env::current_dir()?;
         tmp = cur_dir.join(path);
         path = &tmp;
     }
 
-    let f = create_named(path, &mut OpenOptions::new(), None)?;
+    let f = create_named(path, &mut OpenOptions::new())?;
     // don't care whether the path has already been unlinked,
     // but perhaps there are some IO error conditions we should send up?
     let _ = fs::remove_file(path);
@@ -53,19 +70,16 @@
 
 #[cfg(target_os = "linux")]
 pub fn create(dir: &Path) -> io::Result<File> {
-    use rustix::{fs::OFlags, io::Errno};
-    use std::os::unix::fs::OpenOptionsExt;
+    use libc::{EISDIR, ENOENT, EOPNOTSUPP, O_TMPFILE};
     OpenOptions::new()
         .read(true)
         .write(true)
-        .custom_flags(OFlags::TMPFILE.bits() as i32) // do not mix with `create_new(true)`
+        .custom_flags(O_TMPFILE) // do not mix with `create_new(true)`
         .open(dir)
         .or_else(|e| {
-            match Errno::from_io_error(&e) {
+            match e.raw_os_error() {
                 // These are the three "not supported" error codes for O_TMPFILE.
-                Some(Errno::OPNOTSUPP) | Some(Errno::ISDIR) | Some(Errno::NOENT) => {
-                    create_unix(dir)
-                }
+                Some(EOPNOTSUPP) | Some(EISDIR) | Some(ENOENT) => create_unix(dir),
                 _ => Err(e),
             }
         })
@@ -110,44 +124,31 @@
 
 #[cfg(not(target_os = "redox"))]
 pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
-    if overwrite {
-        rename(old_path, 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, CWD};
-            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()),
-                }
-            }
+    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);
         }
-
-        // Otherwise use `hard_link` to create the new filesystem name, which
-        // will fail if the name already exists, and then `unlink` to remove
-        // the old name.
-        hard_link(old_path, new_path)?;
-
-        // Ignore unlink errors. Can we do better?
-        let _ = unlink(old_path);
+        Ok(())
     }
-    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
-    use rustix::io::Errno;
-    Err(Errno::NOSYS.into())
+    Err(io::Error::from_raw_os_error(syscall::ENOSYS))
 }
 
 pub fn keep(_: &Path) -> io::Result<()> {
diff --git a/crates/tempfile/src/file/imp/windows.rs b/crates/tempfile/src/file/imp/windows.rs
index e7f6038..71b4748 100644
--- a/crates/tempfile/src/file/imp/windows.rs
+++ b/crates/tempfile/src/file/imp/windows.rs
@@ -6,12 +6,13 @@
 use std::path::Path;
 use std::{io, iter};
 
-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 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 crate::util;
 
@@ -19,18 +20,7 @@
     s.as_os_str().encode_wide().chain(iter::once(0)).collect()
 }
 
-fn not_supported<T>(msg: &str) -> io::Result<T> {
-    Err(io::Error::new(io::ErrorKind::Other, msg))
-}
-
-pub fn create_named(
-    path: &Path,
-    open_options: &mut OpenOptions,
-    permissions: Option<&std::fs::Permissions>,
-) -> io::Result<File> {
-    if permissions.map_or(false, |p| p.readonly()) {
-        return not_supported("changing permissions is not supported on this platform");
-    }
+pub fn create_named(path: &Path, open_options: &mut OpenOptions) -> io::Result<File> {
     open_options
         .create_new(true)
         .read(true)
@@ -86,6 +76,9 @@
 }
 
 pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
+    // TODO: We should probably do this in one-shot using SetFileInformationByHandle but the API is
+    // really painful.
+
     unsafe {
         let old_path_w = to_utf16(old_path);
         let new_path_w = to_utf16(new_path);
diff --git a/crates/tempfile/src/file/mod.rs b/crates/tempfile/src/file/mod.rs
index 8930da0..b859ced 100644
--- a/crates/tempfile/src/file/mod.rs
+++ b/crates/tempfile/src/file/mod.rs
@@ -1,3 +1,4 @@
+use std::env;
 use std::error;
 use std::ffi::OsStr;
 use std::fmt;
@@ -5,15 +6,8 @@
 use std::io::{self, Read, Seek, SeekFrom, Write};
 use std::mem;
 use std::ops::Deref;
-#[cfg(unix)]
-use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
-#[cfg(target_os = "wasi")]
-use std::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
-#[cfg(windows)]
-use std::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, RawHandle};
 use std::path::{Path, PathBuf};
 
-use crate::env;
 use crate::error::IoResultExt;
 use crate::Builder;
 
@@ -21,7 +15,7 @@
 
 /// Create a new temporary file.
 ///
-/// The file will be created in the location returned by [`env::temp_dir()`].
+/// The file will be created in the location returned by [`std::env::temp_dir()`].
 ///
 /// # Security
 ///
@@ -40,16 +34,25 @@
 ///
 /// ```
 /// use tempfile::tempfile;
-/// use std::io::Write;
+/// use std::io::{self, Write};
 ///
-/// // Create a file inside of `env::temp_dir()`.
+/// # 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::<(), std::io::Error>(())
+/// # Ok(())
+/// # }
 /// ```
+///
+/// [`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.
@@ -57,7 +60,7 @@
 /// # Security
 ///
 /// This variant is secure/reliable in the presence of a pathological temporary file cleaner.
-/// If the temporary file isn't created in [`env::temp_dir()`] then temporary file cleaners aren't an issue.
+/// If the temporary file isn't created in [`std::env::temp_dir()`] then temporary file cleaners aren't an issue.
 ///
 /// # Resource Leaking
 ///
@@ -72,14 +75,23 @@
 ///
 /// ```
 /// use tempfile::tempfile_in;
-/// use std::io::Write;
+/// 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 the current working directory
 /// let mut file = tempfile_in("./")?;
 ///
 /// writeln!(file, "Brian was here. Briefly.")?;
-/// # Ok::<(), std::io::Error>(())
+/// # Ok(())
+/// # }
 /// ```
+///
+/// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
 pub fn tempfile_in<P: AsRef<Path>>(dir: P) -> io::Result<File> {
     imp::create(dir.as_ref())
 }
@@ -124,11 +136,9 @@
 /// This is useful when the temporary file needs to be used by a child process,
 /// for example.
 ///
-/// When dropped, the temporary file is deleted unless `keep(true)` was called
-/// on the builder that constructed this value.
+/// When dropped, the temporary file is deleted.
 pub struct TempPath {
     path: Box<Path>,
-    keep: bool,
 }
 
 impl TempPath {
@@ -143,8 +153,15 @@
     /// # Examples
     ///
     /// ```no_run
+    /// # use std::io;
     /// use tempfile::NamedTempFile;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), io::Error> {
     /// let file = NamedTempFile::new()?;
     ///
     /// // Close the file, but keep the path to it around.
@@ -155,7 +172,8 @@
     /// // file will still be deleted when `file` goes out of scope, but we
     /// // won't know whether deleting the file succeeded.
     /// path.close()?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     pub fn close(mut self) -> io::Result<()> {
         let result = fs::remove_file(&self.path).with_err_path(|| &*self.path);
@@ -188,15 +206,22 @@
     /// # Examples
     ///
     /// ```no_run
-    /// use std::io::Write;
+    /// # use std::io::{self, Write};
     /// use tempfile::NamedTempFile;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), io::Error> {
     /// let mut file = NamedTempFile::new()?;
     /// writeln!(file, "Brian was here. Briefly.")?;
     ///
     /// let path = file.into_temp_path();
     /// path.persist("./saved_file.txt")?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// [`PathPersistError`]: struct.PathPersistError.html
@@ -240,15 +265,22 @@
     /// # Examples
     ///
     /// ```no_run
+    /// # use std::io::{self, Write};
     /// use tempfile::NamedTempFile;
-    /// use std::io::Write;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), io::Error> {
     /// let mut file = NamedTempFile::new()?;
     /// writeln!(file, "Brian was here. Briefly.")?;
     ///
     /// let path = file.into_temp_path();
     /// path.persist_noclobber("./saved_file.txt")?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// [`PathPersistError`]: struct.PathPersistError.html
@@ -275,6 +307,7 @@
     /// Keep the temporary file from being deleted. This function will turn the
     /// temporary file into a non-temporary file without moving it.
     ///
+    ///
     /// # Errors
     ///
     /// On some platforms (e.g., Windows), we need to mark the file as
@@ -283,15 +316,22 @@
     /// # Examples
     ///
     /// ```no_run
-    /// use std::io::Write;
+    /// # use std::io::{self, Write};
     /// use tempfile::NamedTempFile;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), io::Error> {
     /// let mut file = NamedTempFile::new()?;
     /// writeln!(file, "Brian was here. Briefly.")?;
     ///
     /// let path = file.into_temp_path();
     /// let path = path.keep()?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// [`PathPersistError`]: struct.PathPersistError.html
@@ -321,14 +361,6 @@
     pub fn from_path(path: impl Into<PathBuf>) -> Self {
         Self {
             path: path.into().into_boxed_path(),
-            keep: false,
-        }
-    }
-
-    pub(crate) fn new(path: PathBuf, keep: bool) -> Self {
-        Self {
-            path: path.into_boxed_path(),
-            keep,
         }
     }
 }
@@ -341,9 +373,7 @@
 
 impl Drop for TempPath {
     fn drop(&mut self) {
-        if !self.keep {
-            let _ = fs::remove_file(&self.path);
-        }
+        let _ = fs::remove_file(&self.path);
     }
 }
 
@@ -370,7 +400,7 @@
 /// A named temporary file.
 ///
 /// The default constructor, [`NamedTempFile::new()`], creates files in
-/// the location returned by [`env::temp_dir()`], but `NamedTempFile`
+/// the location returned by [`std::env::temp_dir()`], but `NamedTempFile`
 /// can be configured to manage a temporary file in any location
 /// by constructing with [`NamedTempFile::new_in()`].
 ///
@@ -437,30 +467,29 @@
 /// # Resource Leaking
 ///
 /// If the program exits before the `NamedTempFile` destructor is
-/// 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`]).
+/// run, such as via [`std::process::exit()`], by segfaulting, or by
+/// receiving a signal like `SIGINT`, then the temporary file
+/// will not be deleted.
 ///
-/// Use the [`tempfile()`] function unless you need a named file path.
+/// Use the [`tempfile()`] function unless you absolutely need a named file.
 ///
 /// [`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
-/// [`lazy_static`]: https://github.com/rust-lang-nursery/lazy-static.rs/issues/62
-pub struct NamedTempFile<F = File> {
+pub struct NamedTempFile {
     path: TempPath,
-    file: F,
+    file: File,
 }
 
-impl<F> fmt::Debug for NamedTempFile<F> {
+impl fmt::Debug for NamedTempFile {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "NamedTempFile({:?})", self.path)
     }
 }
 
-impl<F> AsRef<Path> for NamedTempFile<F> {
+impl AsRef<Path> for NamedTempFile {
     #[inline]
     fn as_ref(&self) -> &Path {
         self.path()
@@ -468,46 +497,41 @@
 }
 
 /// Error returned when persisting a temporary file fails.
-pub struct PersistError<F = File> {
+#[derive(Debug)]
+pub struct PersistError {
     /// The underlying IO error.
     pub error: io::Error,
     /// The temporary file that couldn't be persisted.
-    pub file: NamedTempFile<F>,
+    pub file: NamedTempFile,
 }
 
-impl<F> fmt::Debug for PersistError<F> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "PersistError({:?})", self.error)
-    }
-}
-
-impl<F> From<PersistError<F>> for io::Error {
+impl From<PersistError> for io::Error {
     #[inline]
-    fn from(error: PersistError<F>) -> io::Error {
+    fn from(error: PersistError) -> io::Error {
         error.error
     }
 }
 
-impl<F> From<PersistError<F>> for NamedTempFile<F> {
+impl From<PersistError> for NamedTempFile {
     #[inline]
-    fn from(error: PersistError<F>) -> NamedTempFile<F> {
+    fn from(error: PersistError) -> NamedTempFile {
         error.file
     }
 }
 
-impl<F> fmt::Display for PersistError<F> {
+impl fmt::Display for PersistError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "failed to persist temporary file: {}", self.error)
     }
 }
 
-impl<F> error::Error for PersistError<F> {
+impl error::Error for PersistError {
     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
         Some(&self.error)
     }
 }
 
-impl NamedTempFile<File> {
+impl NamedTempFile {
     /// Create a new named temporary file.
     ///
     /// See [`Builder`] for more configuration.
@@ -548,13 +572,20 @@
     /// Create a named temporary file and write some data to it:
     ///
     /// ```no_run
-    /// use std::io::Write;
+    /// # use std::io::{self, Write};
     /// use tempfile::NamedTempFile;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), ::std::io::Error> {
     /// let mut file = NamedTempFile::new()?;
     ///
     /// writeln!(file, "Brian was here. Briefly.")?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// [`Builder`]: struct.Builder.html
@@ -564,12 +595,6 @@
 
     /// Create a new named temporary file in the specified directory.
     ///
-    /// This is equivalent to:
-    ///
-    /// ```ignore
-    /// Builder::new().tempfile_in(dir)
-    /// ```
-    ///
     /// See [`NamedTempFile::new()`] for details.
     ///
     /// [`NamedTempFile::new()`]: #method.new
@@ -577,35 +602,6 @@
         Builder::new().tempfile_in(dir)
     }
 
-    /// Create a new named temporary file with the specified filename prefix.
-    ///
-    /// See [`NamedTempFile::new()`] for details.
-    ///
-    /// [`NamedTempFile::new()`]: #method.new
-    pub fn with_prefix<S: AsRef<OsStr>>(prefix: S) -> io::Result<NamedTempFile> {
-        Builder::new().prefix(&prefix).tempfile()
-    }
-    /// Create a new named temporary file with the specified filename prefix,
-    /// in the specified directory.
-    ///
-    /// This is equivalent to:
-    ///
-    /// ```ignore
-    /// Builder::new().prefix(&prefix).tempfile_in(directory)
-    /// ```
-    ///
-    /// See [`NamedTempFile::new()`] for details.
-    ///
-    /// [`NamedTempFile::new()`]: #method.new
-    pub fn with_prefix_in<S: AsRef<OsStr>, P: AsRef<Path>>(
-        prefix: S,
-        dir: P,
-    ) -> io::Result<NamedTempFile> {
-        Builder::new().prefix(&prefix).tempfile_in(dir)
-    }
-}
-
-impl<F> NamedTempFile<F> {
     /// Get the temporary file's path.
     ///
     /// # Security
@@ -617,12 +613,20 @@
     /// # Examples
     ///
     /// ```no_run
+    /// # use std::io::{self, Write};
     /// use tempfile::NamedTempFile;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), ::std::io::Error> {
     /// let file = NamedTempFile::new()?;
     ///
     /// println!("{:?}", file.path());
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     #[inline]
     pub fn path(&self) -> &Path {
@@ -640,8 +644,15 @@
     /// # Examples
     ///
     /// ```no_run
+    /// # use std::io;
     /// use tempfile::NamedTempFile;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), io::Error> {
     /// let file = NamedTempFile::new()?;
     ///
     /// // By closing the `NamedTempFile` explicitly, we can check that it has
@@ -650,7 +661,8 @@
     /// // of scope, but we won't know whether deleting the file
     /// // succeeded.
     /// file.close()?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     pub fn close(self) -> io::Result<()> {
         let NamedTempFile { path, .. } = self;
@@ -671,7 +683,7 @@
     /// # Security
     ///
     /// This method persists the temporary file using its path and may not be
-    /// secure in all cases. Please read the security section on the top
+    /// secure in the in all cases. Please read the security section on the top
     /// level documentation of this type for details.
     ///
     /// # Errors
@@ -681,18 +693,25 @@
     /// # Examples
     ///
     /// ```no_run
-    /// use std::io::Write;
+    /// # use std::io::{self, Write};
     /// use tempfile::NamedTempFile;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), io::Error> {
     /// let file = NamedTempFile::new()?;
     ///
     /// let mut persisted_file = file.persist("./saved_file.txt")?;
     /// writeln!(persisted_file, "Brian was here. Briefly.")?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// [`PersistError`]: struct.PersistError.html
-    pub fn persist<P: AsRef<Path>>(self, new_path: P) -> Result<F, PersistError<F>> {
+    pub fn persist<P: AsRef<Path>>(self, new_path: P) -> Result<File, PersistError> {
         let NamedTempFile { path, file } = self;
         match path.persist(new_path) {
             Ok(_) => Ok(file),
@@ -718,7 +737,7 @@
     /// # Security
     ///
     /// This method persists the temporary file using its path and may not be
-    /// secure in all cases. Please read the security section on the top
+    /// secure in the in all cases. Please read the security section on the top
     /// level documentation of this type for details.
     ///
     /// # Errors
@@ -729,16 +748,23 @@
     /// # Examples
     ///
     /// ```no_run
-    /// use std::io::Write;
+    /// # use std::io::{self, Write};
     /// use tempfile::NamedTempFile;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), io::Error> {
     /// let file = NamedTempFile::new()?;
     ///
     /// let mut persisted_file = file.persist_noclobber("./saved_file.txt")?;
     /// writeln!(persisted_file, "Brian was here. Briefly.")?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
-    pub fn persist_noclobber<P: AsRef<Path>>(self, new_path: P) -> Result<F, PersistError<F>> {
+    pub fn persist_noclobber<P: AsRef<Path>>(self, new_path: P) -> Result<File, PersistError> {
         let NamedTempFile { path, file } = self;
         match path.persist_noclobber(new_path) {
             Ok(_) => Ok(file),
@@ -764,18 +790,25 @@
     /// # Examples
     ///
     /// ```no_run
-    /// use std::io::Write;
+    /// # use std::io::{self, Write};
     /// use tempfile::NamedTempFile;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), io::Error> {
     /// let mut file = NamedTempFile::new()?;
     /// writeln!(file, "Brian was here. Briefly.")?;
     ///
     /// let (file, path) = file.keep()?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// [`PathPersistError`]: struct.PathPersistError.html
-    pub fn keep(self) -> Result<(F, PathBuf), PersistError<F>> {
+    pub fn keep(self) -> Result<(File, PathBuf), PersistError> {
         let (file, path) = (self.file, self.path);
         match path.keep() {
             Ok(path) => Ok((file, path)),
@@ -786,49 +819,6 @@
         }
     }
 
-    /// 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
@@ -849,78 +839,73 @@
     /// # Examples
     ///
     /// ```no_run
+    /// # use std::io;
     /// use tempfile::NamedTempFile;
     ///
+    /// # fn main() {
+    /// #     if let Err(_) = run() {
+    /// #         ::std::process::exit(1);
+    /// #     }
+    /// # }
+    /// # fn run() -> Result<(), io::Error> {
     /// let file = NamedTempFile::new()?;
     ///
     /// let another_handle = file.reopen()?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     pub fn reopen(&self) -> io::Result<File> {
         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<F: Read> Read for NamedTempFile<F> {
+impl Read for NamedTempFile {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.as_file_mut().read(buf).with_err_path(|| self.path())
     }
-
-    fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
-        self.as_file_mut()
-            .read_vectored(bufs)
-            .with_err_path(|| self.path())
-    }
-
-    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        self.as_file_mut()
-            .read_to_end(buf)
-            .with_err_path(|| self.path())
-    }
-
-    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
-        self.as_file_mut()
-            .read_to_string(buf)
-            .with_err_path(|| self.path())
-    }
-
-    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
-        self.as_file_mut()
-            .read_exact(buf)
-            .with_err_path(|| self.path())
-    }
 }
 
-impl Read for &NamedTempFile<File> {
+impl<'a> Read for &'a NamedTempFile {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.as_file().read(buf).with_err_path(|| self.path())
     }
-
-    fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
-        self.as_file()
-            .read_vectored(bufs)
-            .with_err_path(|| self.path())
-    }
-
-    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        self.as_file()
-            .read_to_end(buf)
-            .with_err_path(|| self.path())
-    }
-
-    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
-        self.as_file()
-            .read_to_string(buf)
-            .with_err_path(|| self.path())
-    }
-
-    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
-        self.as_file().read_exact(buf).with_err_path(|| self.path())
-    }
 }
 
-impl<F: Write> Write for NamedTempFile<F> {
+impl Write for NamedTempFile {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.as_file_mut().write(buf).with_err_path(|| self.path())
     }
@@ -928,27 +913,9 @@
     fn flush(&mut self) -> io::Result<()> {
         self.as_file_mut().flush().with_err_path(|| self.path())
     }
-
-    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
-        self.as_file_mut()
-            .write_vectored(bufs)
-            .with_err_path(|| self.path())
-    }
-
-    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        self.as_file_mut()
-            .write_all(buf)
-            .with_err_path(|| self.path())
-    }
-
-    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
-        self.as_file_mut()
-            .write_fmt(fmt)
-            .with_err_path(|| self.path())
-    }
 }
 
-impl Write for &NamedTempFile<File> {
+impl<'a> Write for &'a NamedTempFile {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.as_file().write(buf).with_err_path(|| self.path())
     }
@@ -956,61 +923,32 @@
     fn flush(&mut self) -> io::Result<()> {
         self.as_file().flush().with_err_path(|| self.path())
     }
-
-    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
-        self.as_file()
-            .write_vectored(bufs)
-            .with_err_path(|| self.path())
-    }
-
-    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        self.as_file().write_all(buf).with_err_path(|| self.path())
-    }
-
-    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
-        self.as_file().write_fmt(fmt).with_err_path(|| self.path())
-    }
 }
 
-impl<F: Seek> Seek for NamedTempFile<F> {
+impl Seek for NamedTempFile {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         self.as_file_mut().seek(pos).with_err_path(|| self.path())
     }
 }
 
-impl Seek for &NamedTempFile<File> {
+impl<'a> Seek for &'a NamedTempFile {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         self.as_file().seek(pos).with_err_path(|| self.path())
     }
 }
 
-#[cfg(any(unix, target_os = "wasi"))]
-impl<F: AsFd> AsFd for NamedTempFile<F> {
-    fn as_fd(&self) -> BorrowedFd<'_> {
-        self.as_file().as_fd()
-    }
-}
-
-#[cfg(any(unix, target_os = "wasi"))]
-impl<F: AsRawFd> AsRawFd for NamedTempFile<F> {
+#[cfg(unix)]
+impl std::os::unix::io::AsRawFd for NamedTempFile {
     #[inline]
-    fn as_raw_fd(&self) -> RawFd {
+    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
         self.as_file().as_raw_fd()
     }
 }
 
 #[cfg(windows)]
-impl<F: AsHandle> AsHandle for NamedTempFile<F> {
+impl std::os::windows::io::AsRawHandle for NamedTempFile {
     #[inline]
-    fn as_handle(&self) -> BorrowedHandle<'_> {
-        self.as_file().as_handle()
-    }
-}
-
-#[cfg(windows)]
-impl<F: AsRawHandle> AsRawHandle for NamedTempFile<F> {
-    #[inline]
-    fn as_raw_handle(&self) -> RawHandle {
+    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
         self.as_file().as_raw_handle()
     }
 }
@@ -1018,20 +956,17 @@
 pub(crate) fn create_named(
     mut path: PathBuf,
     open_options: &mut OpenOptions,
-    permissions: Option<&std::fs::Permissions>,
-    keep: bool,
 ) -> io::Result<NamedTempFile> {
     // Make the path absolute. Otherwise, changing directories could cause us to
     // delete the wrong file.
     if !path.is_absolute() {
-        path = std::env::current_dir()?.join(path)
+        path = env::current_dir()?.join(path)
     }
-    imp::create_named(&path, open_options, permissions)
+    imp::create_named(&path, open_options)
         .with_err_path(|| path.clone())
         .map(|file| NamedTempFile {
             path: TempPath {
                 path: path.into_boxed_path(),
-                keep,
             },
             file,
         })
diff --git a/crates/tempfile/src/lib.rs b/crates/tempfile/src/lib.rs
index ca657cb..c38ca7b 100644
--- a/crates/tempfile/src/lib.rs
+++ b/crates/tempfile/src/lib.rs
@@ -14,12 +14,9 @@
 //!
 //! ## 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.
+//! `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
 //!
@@ -37,10 +34,16 @@
 //! generic over `AsRef<Path>`. Consider the following example:
 //!
 //! ```no_run
-//! use tempfile::tempdir;
-//! use std::process::Command;
-//!
-//! // Create a directory inside of `env::temp_dir()`.
+//! # 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
@@ -48,7 +51,8 @@
 //! let exit_status = Command::new("touch").arg("tmp").current_dir(&temp_dir).status()?;
 //! assert!(exit_status.success());
 //!
-//! # Ok::<(), std::io::Error>(())
+//! # Ok(())
+//! # }
 //! ```
 //!
 //! This works because a reference to `temp_dir` is passed to `current_dir`, resulting in the
@@ -65,24 +69,37 @@
 //!
 //! ```
 //! use tempfile::tempfile;
-//! use std::io::Write;
+//! use std::io::{self, Write};
 //!
-//! // Create a file inside of `env::temp_dir()`.
+//! # 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::<(), std::io::Error>(())
+//! # Ok(())
+//! # }
 //! ```
 //!
 //! Create a named temporary file and open an independent file handle:
 //!
 //! ```
 //! use tempfile::NamedTempFile;
-//! use std::io::{Write, Read};
+//! 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 `env::temp_dir()`.
+//! // Create a file inside of `std::env::temp_dir()`.
 //! let mut file1 = NamedTempFile::new()?;
 //!
 //! // Re-open it.
@@ -95,7 +112,8 @@
 //! let mut buf = String::new();
 //! file2.read_to_string(&mut buf)?;
 //! assert_eq!(buf, text);
-//! # Ok::<(), std::io::Error>(())
+//! # Ok(())
+//! # }
 //! ```
 //!
 //! Create a temporary directory and add a file to it:
@@ -103,9 +121,15 @@
 //! ```
 //! use tempfile::tempdir;
 //! use std::fs::File;
-//! use std::io::Write;
+//! use std::io::{self, Write};
 //!
-//! // Create a directory inside of `env::temp_dir()`.
+//! # 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");
@@ -119,24 +143,25 @@
 //! // succeeded.
 //! drop(file);
 //! dir.close()?;
-//! # Ok::<(), std::io::Error>(())
+//! # Ok(())
+//! # }
 //! ```
 //!
 //! [`tempfile()`]: fn.tempfile.html
 //! [`tempdir()`]: fn.tempdir.html
 //! [`TempDir`]: struct.TempDir.html
 //! [`NamedTempFile`]: struct.NamedTempFile.html
-//! [`lazy_static`]: https://github.com/rust-lang-nursery/lazy-static.rs/issues/62
+//! [`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/latest"
+    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_attr(feature = "nightly", feature(wasi_ext))]
 
 #[cfg(doctest)]
 doc_comment::doctest!("../README.md");
@@ -146,8 +171,8 @@
 
 use std::ffi::OsStr;
 use std::fs::OpenOptions;
-use std::io;
 use std::path::Path;
+use std::{env, io};
 
 mod dir;
 mod error;
@@ -155,8 +180,6 @@
 mod spooled;
 mod util;
 
-pub mod env;
-
 pub use crate::dir::{tempdir, tempdir_in, TempDir};
 pub use crate::file::{
     tempfile, tempfile_in, NamedTempFile, PathPersistError, PersistError, TempPath,
@@ -170,8 +193,6 @@
     prefix: &'a OsStr,
     suffix: &'b OsStr,
     append: bool,
-    permissions: Option<std::fs::Permissions>,
-    keep: bool,
 }
 
 impl<'a, 'b> Default for Builder<'a, 'b> {
@@ -181,8 +202,6 @@
             prefix: OsStr::new(".tmp"),
             suffix: OsStr::new(""),
             append: false,
-            permissions: None,
-            keep: false,
         }
     }
 }
@@ -195,7 +214,14 @@
     /// Create a named temporary file and write some data into it:
     ///
     /// ```
-    /// use std::ffi::OsStr;
+    /// # 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()
@@ -213,15 +239,22 @@
     ///     assert!(name.ends_with(".txt"));
     ///     assert_eq!(name.len(), "my-temporary-note.txt".len() + 5);
     /// }
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// Create a temporary directory and add a file to it:
     ///
     /// ```
-    /// use std::io::Write;
-    /// use std::fs::File;
-    /// use std::ffi::OsStr;
+    /// # 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()
@@ -240,20 +273,9 @@
     /// // succeeded.
     /// drop(file);
     /// dir.close()?;
-    /// # Ok::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
-    ///
-    /// Create a temporary directory with a chosen prefix under a chosen folder:
-    ///
-    /// ```no_run
-    /// use tempfile::Builder;
-    ///
-    /// let dir = Builder::new()
-    ///     .prefix("my-temporary-dir")
-    ///     .tempdir_in("folder-with-tempdirs")?;
-    /// # Ok::<(), std::io::Error>(())
-    /// ```
-    #[must_use]
     pub fn new() -> Self {
         Self::default()
     }
@@ -266,12 +288,19 @@
     /// # Examples
     ///
     /// ```
-    /// use tempfile::Builder;
-    ///
+    /// # 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::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     pub fn prefix<S: AsRef<OsStr> + ?Sized>(&mut self, prefix: &'a S) -> &mut Self {
         self.prefix = prefix.as_ref();
@@ -286,12 +315,19 @@
     /// # Examples
     ///
     /// ```
-    /// use tempfile::Builder;
-    ///
+    /// # 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::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     pub fn suffix<S: AsRef<OsStr> + ?Sized>(&mut self, suffix: &'b S) -> &mut Self {
         self.suffix = suffix.as_ref();
@@ -305,12 +341,19 @@
     /// # Examples
     ///
     /// ```
-    /// use tempfile::Builder;
-    ///
+    /// # 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::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     pub fn rand_bytes(&mut self, rand: usize) -> &mut Self {
         self.random_len = rand;
@@ -324,108 +367,25 @@
     /// # Examples
     ///
     /// ```
-    /// use tempfile::Builder;
-    ///
+    /// # 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::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     pub fn append(&mut self, append: bool) -> &mut Self {
         self.append = append;
         self
     }
 
-    /// The permissions to create the tempfile or [tempdir](Self::tempdir) with.
-    /// This allows to them differ from the default mode of `0o600` on Unix.
-    ///
-    /// # Security
-    ///
-    /// By default, the permissions of tempfiles on unix are set for it to be
-    /// readable and writable by the owner only, yielding the greatest amount
-    /// of security.
-    /// As this method allows to widen the permissions, security would be
-    /// reduced in such cases.
-    ///
-    /// # Platform Notes
-    /// ## Unix
-    ///
-    /// The actual permission bits set on the tempfile or tempdir will be affected by the
-    /// `umask` applied by the underlying syscall.
-    ///
-    ///
-    /// ## Windows and others
-    ///
-    /// This setting is unsupported and trying to set a file or directory read-only
-    /// will cause an error to be returned..
-    ///
-    /// # Examples
-    ///
-    /// Create a named temporary file that is world-readable.
-    ///
-    /// ```
-    /// # #[cfg(unix)]
-    /// # {
-    /// use tempfile::Builder;
-    /// use std::os::unix::fs::PermissionsExt;
-    ///
-    /// let all_read_write = std::fs::Permissions::from_mode(0o666);
-    /// let tempfile = Builder::new().permissions(all_read_write).tempfile()?;
-    /// let actual_permissions = tempfile.path().metadata()?.permissions();
-    /// assert_ne!(
-    ///     actual_permissions.mode() & !0o170000,
-    ///     0o600,
-    ///     "we get broader permissions than the default despite umask"
-    /// );
-    /// # }
-    /// # Ok::<(), std::io::Error>(())
-    /// ```
-    ///
-    /// Create a named temporary directory that is restricted to the owner.
-    ///
-    /// ```
-    /// # #[cfg(unix)]
-    /// # {
-    /// use tempfile::Builder;
-    /// use std::os::unix::fs::PermissionsExt;
-    ///
-    /// let owner_rwx = std::fs::Permissions::from_mode(0o700);
-    /// let tempdir = Builder::new().permissions(owner_rwx).tempdir()?;
-    /// let actual_permissions = tempdir.path().metadata()?.permissions();
-    /// assert_eq!(
-    ///     actual_permissions.mode() & !0o170000,
-    ///     0o700,
-    ///     "we get the narrow permissions we asked for"
-    /// );
-    /// # }
-    /// # Ok::<(), std::io::Error>(())
-    /// ```
-    pub fn permissions(&mut self, permissions: std::fs::Permissions) -> &mut Self {
-        self.permissions = Some(permissions);
-        self
-    }
-
-    /// Set the file/folder to be kept even when the [`NamedTempFile`]/[`TempDir`] goes out of
-    /// scope.
-    ///
-    /// By default, the file/folder is automatically cleaned up in the destructor of
-    /// [`NamedTempFile`]/[`TempDir`]. When `keep` is set to `true`, this behavior is supressed.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use tempfile::Builder;
-    ///
-    /// let named_tempfile = Builder::new()
-    ///     .keep(true)
-    ///     .tempfile()?;
-    /// # Ok::<(), std::io::Error>(())
-    /// ```
-    pub fn keep(&mut self, keep: bool) -> &mut Self {
-        self.keep = keep;
-        self
-    }
-
     /// Create the named temporary file.
     ///
     /// # Security
@@ -443,16 +403,23 @@
     /// # Examples
     ///
     /// ```
-    /// use tempfile::Builder;
-    ///
+    /// # 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::<(), std::io::Error>(())
+    /// # 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())
+        self.tempfile_in(&env::temp_dir())
     }
 
     /// Create the named temporary file in the specified directory.
@@ -472,10 +439,17 @@
     /// # Examples
     ///
     /// ```
-    /// use tempfile::Builder;
-    ///
+    /// # 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::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// [security]: struct.NamedTempFile.html#security
@@ -486,18 +460,11 @@
             self.prefix,
             self.suffix,
             self.random_len,
-            |path| {
-                file::create_named(
-                    path,
-                    OpenOptions::new().append(self.append),
-                    self.permissions.as_ref(),
-                    self.keep,
-                )
-            },
+            |path| file::create_named(path, OpenOptions::new().append(self.append)),
         )
     }
 
-    /// Attempts to make a temporary directory inside of [`env::temp_dir()`] whose
+    /// 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.
@@ -513,15 +480,20 @@
     /// # 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::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// [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`.
@@ -539,10 +511,15 @@
     /// # 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::<(), std::io::Error>(())
+    /// # Ok(())
+    /// # }
     /// ```
     ///
     /// [resource-leaking]: struct.TempDir.html#resource-leaking
@@ -550,140 +527,11 @@
         let storage;
         let mut dir = dir.as_ref();
         if !dir.is_absolute() {
-            let cur_dir = std::env::current_dir()?;
+            let cur_dir = env::current_dir()?;
             storage = cur_dir.join(dir);
             dir = &storage;
         }
 
-        util::create_helper(dir, self.prefix, self.suffix, self.random_len, |path| {
-            dir::create(path, self.permissions.as_ref(), self.keep)
-        })
-    }
-
-    /// 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 [`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::fs::File;
-    /// use tempfile::Builder;
-    ///
-    /// // This is NOT secure!
-    /// let tempfile = Builder::new().make(|path| {
-    ///     if path.is_file() {
-    ///         return Err(std::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::<(), std::io::Error>(())
-    /// ```
-    ///
-    /// Note that simply using [`std::fs::File::create`] alone is not correct
-    /// because it does not fail if the file already exists:
-    ///
-    /// ```
-    /// use tempfile::Builder;
-    /// use std::fs::File;
-    ///
-    /// // This could overwrite an existing file!
-    /// let tempfile = Builder::new().make(|path| File::create(path))?;
-    /// # Ok::<(), std::io::Error>(())
-    /// ```
-    /// 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
-    /// ```
-    /// # #[cfg(unix)]
-    /// # {
-    /// use std::os::unix::net::UnixListener;
-    /// use tempfile::Builder;
-    ///
-    /// let tempsock = Builder::new().make(|path| UnixListener::bind(path))?;
-    /// # }
-    /// # Ok::<(), std::io::Error>(())
-    /// ```
-    ///
-    /// [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
-    /// ```
-    /// # #[cfg(unix)]
-    /// # {
-    /// use tempfile::Builder;
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let tempsock = Builder::new().make_in("./", |path| UnixListener::bind(path))?;
-    /// # }
-    /// # Ok::<(), std::io::Error>(())
-    /// ```
-    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::new(path, self.keep),
-                ))
-            },
-        )
+        util::create_helper(dir, self.prefix, self.suffix, self.random_len, dir::create)
     }
 }
diff --git a/crates/tempfile/src/spooled.rs b/crates/tempfile/src/spooled.rs
index 9c9846c..ed6c16f 100644
--- a/crates/tempfile/src/spooled.rs
+++ b/crates/tempfile/src/spooled.rs
@@ -36,8 +36,14 @@
 ///
 /// ```
 /// use tempfile::spooled_tempfile;
-/// use std::io::Write;
+/// use std::io::{self, Write};
 ///
+/// # fn main() {
+/// #     if let Err(_) = run() {
+/// #         ::std::process::exit(1);
+/// #     }
+/// # }
+/// # fn run() -> Result<(), io::Error> {
 /// let mut file = spooled_tempfile(15);
 ///
 /// writeln!(file, "short line")?;
@@ -48,7 +54,9 @@
 /// // and the in-memory buffer will be dropped
 /// writeln!(file, "marvin gardens")?;
 /// assert!(file.is_rolled());
-/// # Ok::<(), std::io::Error>(())
+///
+/// # Ok(())
+/// # }
 /// ```
 #[inline]
 pub fn spooled_tempfile(max_size: usize) -> SpooledTempFile {
@@ -56,16 +64,14 @@
 }
 
 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,
@@ -78,7 +84,7 @@
     pub fn roll(&mut self) -> io::Result<()> {
         if !self.is_rolled() {
             let mut file = tempfile()?;
-            if let SpooledData::InMemory(cursor) = &mut self.inner {
+            if let SpooledData::InMemory(ref mut cursor) = self.inner {
                 file.write_all(cursor.get_ref())?;
                 file.seek(SeekFrom::Start(cursor.position()))?;
             }
@@ -88,20 +94,19 @@
     }
 
     pub fn set_len(&mut self, size: u64) -> Result<(), io::Error> {
-        if size > self.max_size as u64 {
+        if size as usize > self.max_size {
             self.roll()?; // does nothing if already rolled over
         }
-        match &mut self.inner {
-            SpooledData::InMemory(cursor) => {
+        match self.inner {
+            SpooledData::InMemory(ref mut cursor) => {
                 cursor.get_mut().resize(size as usize, 0);
                 Ok(())
             }
-            SpooledData::OnDisk(file) => file.set_len(size),
+            SpooledData::OnDisk(ref mut file) => file.set_len(size),
         }
     }
 
     /// Consumes and returns the inner `SpooledData` type.
-    #[must_use]
     pub fn into_inner(self) -> SpooledData {
         self.inner
     }
@@ -109,37 +114,9 @@
 
 impl Read for SpooledTempFile {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        match &mut self.inner {
-            SpooledData::InMemory(cursor) => cursor.read(buf),
-            SpooledData::OnDisk(file) => file.read(buf),
-        }
-    }
-
-    fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
-        match &mut self.inner {
-            SpooledData::InMemory(cursor) => cursor.read_vectored(bufs),
-            SpooledData::OnDisk(file) => file.read_vectored(bufs),
-        }
-    }
-
-    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        match &mut self.inner {
-            SpooledData::InMemory(cursor) => cursor.read_to_end(buf),
-            SpooledData::OnDisk(file) => file.read_to_end(buf),
-        }
-    }
-
-    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
-        match &mut self.inner {
-            SpooledData::InMemory(cursor) => cursor.read_to_string(buf),
-            SpooledData::OnDisk(file) => file.read_to_string(buf),
-        }
-    }
-
-    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
-        match &mut self.inner {
-            SpooledData::InMemory(cursor) => cursor.read_exact(buf),
-            SpooledData::OnDisk(file) => file.read_exact(buf),
+        match self.inner {
+            SpooledData::InMemory(ref mut cursor) => cursor.read(buf),
+            SpooledData::OnDisk(ref mut file) => file.read(buf),
         }
     }
 }
@@ -147,51 +124,35 @@
 impl Write for SpooledTempFile {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         // roll over to file if necessary
-        if matches! {
-            &self.inner, SpooledData::InMemory(cursor)
-            if cursor.position().saturating_add(buf.len() as u64) > self.max_size as u64
-        } {
+        let mut rolling = false;
+        if let SpooledData::InMemory(ref mut cursor) = self.inner {
+            rolling = cursor.position() as usize + buf.len() > self.max_size;
+        }
+        if rolling {
             self.roll()?;
         }
 
         // write the bytes
-        match &mut self.inner {
-            SpooledData::InMemory(cursor) => cursor.write(buf),
-            SpooledData::OnDisk(file) => file.write(buf),
-        }
-    }
-
-    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
-        if matches! {
-            &self.inner, SpooledData::InMemory(cursor)
-            // Borrowed from the rust standard library.
-            if bufs
-                .iter()
-                .fold(cursor.position(), |a, b| a.saturating_add(b.len() as u64))
-                > self.max_size as u64
-        } {
-            self.roll()?;
-        }
-        match &mut self.inner {
-            SpooledData::InMemory(cursor) => cursor.write_vectored(bufs),
-            SpooledData::OnDisk(file) => file.write_vectored(bufs),
+        match self.inner {
+            SpooledData::InMemory(ref mut cursor) => cursor.write(buf),
+            SpooledData::OnDisk(ref mut file) => file.write(buf),
         }
     }
 
     #[inline]
     fn flush(&mut self) -> io::Result<()> {
-        match &mut self.inner {
-            SpooledData::InMemory(cursor) => cursor.flush(),
-            SpooledData::OnDisk(file) => file.flush(),
+        match self.inner {
+            SpooledData::InMemory(ref mut cursor) => cursor.flush(),
+            SpooledData::OnDisk(ref mut file) => file.flush(),
         }
     }
 }
 
 impl Seek for SpooledTempFile {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-        match &mut self.inner {
-            SpooledData::InMemory(cursor) => cursor.seek(pos),
-            SpooledData::OnDisk(file) => file.seek(pos),
+        match self.inner {
+            SpooledData::InMemory(ref mut cursor) => cursor.seek(pos),
+            SpooledData::OnDisk(ref mut file) => file.seek(pos),
         }
     }
 }
diff --git a/crates/tempfile/src/util.rs b/crates/tempfile/src/util.rs
index 2f6f381..8c91b9c 100644
--- a/crates/tempfile/src/util.rs
+++ b/crates/tempfile/src/util.rs
@@ -1,3 +1,4 @@
+use fastrand;
 use std::ffi::{OsStr, OsString};
 use std::path::{Path, PathBuf};
 use std::{io, iter::repeat_with};
@@ -5,11 +6,7 @@
 use crate::error::IoResultExt;
 
 fn tmpname(prefix: &OsStr, suffix: &OsStr, rand_len: usize) -> OsString {
-    let capacity = prefix
-        .len()
-        .saturating_add(suffix.len())
-        .saturating_add(rand_len);
-    let mut buf = OsString::with_capacity(capacity);
+    let mut buf = OsString::with_capacity(prefix.len() + suffix.len() + rand_len);
     buf.push(prefix);
     let mut char_buf = [0u8; 4];
     for c in repeat_with(fastrand::alphanumeric).take(rand_len) {
@@ -19,13 +16,16 @@
     buf
 }
 
-pub fn create_helper<R>(
+pub fn create_helper<F, R>(
     base: &Path,
     prefix: &OsStr,
     suffix: &OsStr,
     random_len: usize,
-    mut f: impl FnMut(PathBuf) -> io::Result<R>,
-) -> io::Result<R> {
+    f: F,
+) -> io::Result<R>
+where
+    F: Fn(PathBuf) -> io::Result<R>,
+{
     let num_retries = if random_len != 0 {
         crate::NUM_RETRIES
     } else {
@@ -35,10 +35,7 @@
     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 && 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,
+            Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => continue,
             res => res,
         };
     }
diff --git a/crates/tempfile/tests/env.rs b/crates/tempfile/tests/env.rs
deleted file mode 100644
index 558f767..0000000
--- a/crates/tempfile/tests/env.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#![deny(rust_2018_idioms)]
-
-use std::path::Path;
-
-#[test]
-fn test_override_temp_dir() {
-    assert_eq!(tempfile::env::temp_dir(), std::env::temp_dir());
-
-    let new_tmp = Path::new("/tmp/override");
-    tempfile::env::override_temp_dir(&new_tmp).unwrap();
-    assert_eq!(tempfile::env::temp_dir(), new_tmp);
-
-    let new_tmp2 = Path::new("/tmp/override2");
-    tempfile::env::override_temp_dir(new_tmp2).expect_err("override should only be possible once");
-}
diff --git a/crates/tempfile/tests/namedtempfile.rs b/crates/tempfile/tests/namedtempfile.rs
index 06b6e86..d2c7da2 100644
--- a/crates/tempfile/tests/namedtempfile.rs
+++ b/crates/tempfile/tests/namedtempfile.rs
@@ -1,23 +1,17 @@
 #![deny(rust_2018_idioms)]
 
+use std::env;
 use std::ffi::{OsStr, OsString};
 use std::fs::File;
 use std::io::{Read, Seek, SeekFrom, Write};
 use std::path::{Path, PathBuf};
-use tempfile::{env, tempdir, Builder, NamedTempFile, TempPath};
+use tempfile::{tempdir, Builder, NamedTempFile, TempPath};
 
 fn exists<P: AsRef<Path>>(path: P) -> bool {
     std::fs::metadata(path.as_ref()).is_ok()
 }
 
 #[test]
-fn test_prefix() {
-    let tmpfile = NamedTempFile::with_prefix("prefix").unwrap();
-    let name = tmpfile.path().file_name().unwrap().to_str().unwrap();
-    assert!(name.starts_with("prefix"));
-}
-
-#[test]
 fn test_basic() {
     let mut tmpfile = NamedTempFile::new().unwrap();
     write!(tmpfile, "abcde").unwrap();
@@ -93,7 +87,7 @@
 fn test_customnamed() {
     let tmpfile = Builder::new()
         .prefix("tmp")
-        .suffix(&".rs")
+        .suffix(&".rs".to_string())
         .rand_bytes(12)
         .tempfile()
         .unwrap();
@@ -106,9 +100,9 @@
 #[test]
 fn test_append() {
     let mut tmpfile = Builder::new().append(true).tempfile().unwrap();
-    tmpfile.write_all(b"a").unwrap();
+    tmpfile.write(b"a").unwrap();
     tmpfile.seek(SeekFrom::Start(0)).unwrap();
-    tmpfile.write_all(b"b").unwrap();
+    tmpfile.write(b"b").unwrap();
 
     tmpfile.seek(SeekFrom::Start(0)).unwrap();
     let mut buf = vec![0u8; 1];
@@ -275,10 +269,10 @@
 
 #[test]
 fn test_change_dir() {
-    std::env::set_current_dir(env::temp_dir()).unwrap();
+    env::set_current_dir(env::temp_dir()).unwrap();
     let tmpfile = NamedTempFile::new_in(".").unwrap();
-    let path = std::env::current_dir().unwrap().join(tmpfile.path());
-    std::env::set_current_dir("/").unwrap();
+    let path = env::current_dir().unwrap().join(tmpfile.path());
+    env::set_current_dir("/").unwrap();
     drop(tmpfile);
     assert!(!exists(path))
 }
@@ -305,18 +299,6 @@
 }
 
 #[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();
@@ -344,146 +326,3 @@
     }
     std::fs::remove_file(&path).unwrap();
 }
-
-#[test]
-fn test_builder_keep() {
-    let mut tmpfile = Builder::new().keep(true).tempfile().unwrap();
-    write!(tmpfile, "abcde").unwrap();
-    let path = tmpfile.path().to_owned();
-    drop(tmpfile);
-
-    {
-        // Try opening it again.
-        let mut f = File::open(&path).unwrap();
-        let mut buf = String::new();
-        f.read_to_string(&mut buf).unwrap();
-        assert_eq!("abcde", buf);
-    }
-    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/crates/tempfile/tests/spooled.rs b/crates/tempfile/tests/spooled.rs
index 4060214..288d1e6 100644
--- a/crates/tempfile/tests/spooled.rs
+++ b/crates/tempfile/tests/spooled.rs
@@ -10,7 +10,7 @@
     let mut buf = Vec::new();
 
     assert!(!t.is_rolled());
-    assert_eq!(t.stream_position().unwrap(), 0);
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 0);
     assert_eq!(t.read_to_end(&mut buf).unwrap(), 0);
     assert_eq!(buf.as_slice(), b"");
     buf.clear();
@@ -24,7 +24,7 @@
 
     assert_eq!(t.write(b"fghijklmno").unwrap(), 10);
 
-    assert_eq!(t.stream_position().unwrap(), 15);
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 15);
     assert!(t.is_rolled());
 }
 
@@ -32,13 +32,13 @@
 fn test_explicit_rollover() {
     let mut t = SpooledTempFile::new(100);
     assert_eq!(t.write(b"abcdefghijklmnopqrstuvwxyz").unwrap(), 26);
-    assert_eq!(t.stream_position().unwrap(), 26);
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 26);
     assert!(!t.is_rolled());
 
     // roll over explicitly
     assert!(t.roll().is_ok());
     assert!(t.is_rolled());
-    assert_eq!(t.stream_position().unwrap(), 26);
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 26);
 
     let mut buf = Vec::new();
     assert_eq!(t.read_to_end(&mut buf).unwrap(), 0);
@@ -48,7 +48,7 @@
     assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0);
     assert_eq!(t.read_to_end(&mut buf).unwrap(), 26);
     assert_eq!(buf.as_slice(), b"abcdefghijklmnopqrstuvwxyz");
-    assert_eq!(t.stream_position().unwrap(), 26);
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 26);
 }
 
 // called by test_seek_{buffer, file}
@@ -56,7 +56,7 @@
 fn test_seek(t: &mut SpooledTempFile) {
     assert_eq!(t.write(b"abcdefghijklmnopqrstuvwxyz").unwrap(), 26);
 
-    assert_eq!(t.stream_position().unwrap(), 26); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 26); // tell()
     assert_eq!(t.seek(SeekFrom::Current(-1)).unwrap(), 25);
     assert_eq!(t.seek(SeekFrom::Current(1)).unwrap(), 26);
     assert_eq!(t.seek(SeekFrom::Current(1)).unwrap(), 27);
@@ -110,7 +110,7 @@
     buf.clear();
 
     // now we're at the end again
-    assert_eq!(t.stream_position().unwrap(), 26); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 26); // tell()
     assert_eq!(t.read_to_end(&mut buf).unwrap(), 0);
     assert_eq!(buf.as_slice(), b"");
     buf.clear();
@@ -122,7 +122,7 @@
     assert_eq!(buf, *b"fghij");
 
     // read again from current spot
-    assert_eq!(t.stream_position().unwrap(), 10); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 10); // tell()
     assert!(t.read_exact(&mut buf).is_ok());
     assert_eq!(buf, *b"klmno");
 
@@ -190,11 +190,11 @@
     assert_eq!(t.write(b"abcdefghijklmno").unwrap(), 15);
     assert!(!t.is_rolled());
     assert_eq!(t.seek(SeekFrom::End(-5)).unwrap(), 10);
-    assert_eq!(t.stream_position().unwrap(), 10); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 10); // tell()
     assert!(!t.is_rolled());
     assert_eq!(t.write(b"0123456789)!@#$%^&*(").unwrap(), 20);
     assert!(t.is_rolled());
-    assert_eq!(t.stream_position().unwrap(), 30); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 30); // tell()
     let mut buf = Vec::new();
     assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0);
     assert_eq!(t.read_to_end(&mut buf).unwrap(), 30);
@@ -247,11 +247,11 @@
     assert!(t.set_len(10).is_ok());
 
     // position should not have moved
-    assert_eq!(t.stream_position().unwrap(), 26); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 26); // tell()
 
     assert_eq!(t.read_to_end(&mut buf).unwrap(), 0);
     assert_eq!(buf.as_slice(), b"");
-    assert_eq!(t.stream_position().unwrap(), 26); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 26); // tell()
     buf.clear();
 
     // read whole thing
@@ -262,7 +262,7 @@
 
     // set_len to expand beyond the end
     assert!(t.set_len(40).is_ok());
-    assert_eq!(t.stream_position().unwrap(), 10); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 10); // tell()
     assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0);
     assert_eq!(t.read_to_end(&mut buf).unwrap(), 40);
     assert_eq!(
@@ -290,33 +290,18 @@
     let mut t = spooled_tempfile(10);
     assert_eq!(t.write(b"abcde").unwrap(), 5);
     assert!(!t.is_rolled());
-    assert_eq!(t.stream_position().unwrap(), 5); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 5); // tell()
 
     assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0);
     assert_eq!(t.read_to_end(&mut buf).unwrap(), 5);
     assert_eq!(buf.as_slice(), b"abcde");
-    assert_eq!(t.stream_position().unwrap(), 5); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 5); // tell()
     buf.clear();
 
     assert!(t.set_len(20).is_ok());
     assert!(t.is_rolled());
-    assert_eq!(t.stream_position().unwrap(), 5); // tell()
+    assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 5); // tell()
     assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0);
     assert_eq!(t.read_to_end(&mut buf).unwrap(), 20);
     assert_eq!(buf.as_slice(), b"abcde\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
 }
-
-#[test]
-fn test_write_overflow() {
-    let mut t = spooled_tempfile(10);
-    t.seek(SeekFrom::Start(u64::MAX)).unwrap();
-    assert!(t.write(b"abcde").is_err());
-}
-
-#[cfg(target_pointer_width = "32")]
-#[test]
-fn test_set_len_truncation() {
-    let mut t = spooled_tempfile(100);
-    assert!(t.set_len(usize::MAX as u64 + 5).is_ok());
-    assert!(t.is_rolled());
-}
diff --git a/crates/tempfile/tests/tempdir.rs b/crates/tempfile/tests/tempdir.rs
index 93f86ab..746fe47 100644
--- a/crates/tempfile/tests/tempdir.rs
+++ b/crates/tempfile/tests/tempdir.rs
@@ -10,6 +10,7 @@
 
 #![deny(rust_2018_idioms)]
 
+use std::env;
 use std::fs;
 use std::path::Path;
 use std::sync::mpsc::channel;
@@ -17,9 +18,32 @@
 
 use tempfile::{Builder, TempDir};
 
+macro_rules! t {
+    ($e:expr) => {
+        match $e {
+            Ok(n) => n,
+            Err(e) => panic!("error: {}", e),
+        }
+    };
+}
+
+trait PathExt {
+    fn exists(&self) -> bool;
+    fn is_dir(&self) -> bool;
+}
+
+impl PathExt for Path {
+    fn exists(&self) -> bool {
+        fs::metadata(self).is_ok()
+    }
+    fn is_dir(&self) -> bool {
+        fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
+    }
+}
+
 fn test_tempdir() {
     let path = {
-        let p = Builder::new().prefix("foobar").tempdir_in(".").unwrap();
+        let p = t!(Builder::new().prefix("foobar").tempdir_in(&Path::new(".")));
         let p = p.path();
         assert!(p.to_str().unwrap().contains("foobar"));
         p.to_path_buf()
@@ -27,12 +51,7 @@
     assert!(!path.exists());
 }
 
-fn test_prefix() {
-    let tmpfile = TempDir::with_prefix_in("prefix", ".").unwrap();
-    let name = tmpfile.path().file_name().unwrap().to_str().unwrap();
-    assert!(name.starts_with("prefix"));
-}
-
+#[test]
 fn test_customnamed() {
     let tmpfile = Builder::new()
         .prefix("prefix")
@@ -48,8 +67,8 @@
 
 fn test_rm_tempdir() {
     let (tx, rx) = channel();
-    let f = move || {
-        let tmp = TempDir::new().unwrap();
+    let f = move || -> () {
+        let tmp = t!(TempDir::new());
         tx.send(tmp.path().to_path_buf()).unwrap();
         panic!("panic to unwind past `tmp`");
     };
@@ -57,9 +76,9 @@
     let path = rx.recv().unwrap();
     assert!(!path.exists());
 
-    let tmp = TempDir::new().unwrap();
+    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`");
     };
@@ -68,7 +87,7 @@
 
     let path;
     {
-        let f = move || TempDir::new().unwrap();
+        let f = move || t!(TempDir::new());
 
         let tmp = thread::spawn(f).join().unwrap();
         path = tmp.path().to_path_buf();
@@ -78,31 +97,31 @@
 
     let path;
     {
-        let tmp = TempDir::new().unwrap();
+        let tmp = t!(TempDir::new());
         path = tmp.into_path();
     }
     assert!(path.exists());
-    fs::remove_dir_all(&path).unwrap();
+    t!(fs::remove_dir_all(&path));
     assert!(!path.exists());
 }
 
 fn test_rm_tempdir_close() {
     let (tx, rx) = channel();
-    let f = move || {
-        let tmp = TempDir::new().unwrap();
+    let f = move || -> () {
+        let tmp = t!(TempDir::new());
         tx.send(tmp.path().to_path_buf()).unwrap();
-        tmp.close().unwrap();
+        t!(tmp.close());
         panic!("panic when unwinding past `tmp`");
     };
     let _ = thread::spawn(f).join();
     let path = rx.recv().unwrap();
     assert!(!path.exists());
 
-    let tmp = TempDir::new().unwrap();
+    let tmp = t!(TempDir::new());
     let path = tmp.path().to_path_buf();
-    let f = move || {
+    let f = move || -> () {
         let tmp = tmp;
-        tmp.close().unwrap();
+        t!(tmp.close());
         panic!("panic when unwinding past `tmp`");
     };
     let _ = thread::spawn(f).join();
@@ -110,31 +129,96 @@
 
     let path;
     {
-        let f = move || TempDir::new().unwrap();
+        let f = move || t!(TempDir::new());
 
         let tmp = thread::spawn(f).join().unwrap();
         path = tmp.path().to_path_buf();
         assert!(path.exists());
-        tmp.close().unwrap();
+        t!(tmp.close());
     }
     assert!(!path.exists());
 
     let path;
     {
-        let tmp = TempDir::new().unwrap();
+        let tmp = t!(TempDir::new());
         path = tmp.into_path();
     }
     assert!(path.exists());
-    fs::remove_dir_all(&path).unwrap();
+    t!(fs::remove_dir_all(&path));
     assert!(!path.exists());
 }
 
-fn dont_double_panic() {
+// Ideally these would be in std::os but then core would need
+// to depend on std
+fn recursive_mkdir_rel() {
+    let path = Path::new("frob");
+    let cwd = env::current_dir().unwrap();
+    println!(
+        "recursive_mkdir_rel: Making: {} in cwd {} [{}]",
+        path.display(),
+        cwd.display(),
+        path.exists()
+    );
+    t!(fs::create_dir(&path));
+    assert!(path.is_dir());
+    t!(fs::create_dir_all(&path));
+    assert!(path.is_dir());
+}
+
+fn recursive_mkdir_dot() {
+    let dot = Path::new(".");
+    t!(fs::create_dir_all(&dot));
+    let dotdot = Path::new("..");
+    t!(fs::create_dir_all(&dotdot));
+}
+
+fn recursive_mkdir_rel_2() {
+    let path = Path::new("./frob/baz");
+    let cwd = env::current_dir().unwrap();
+    println!(
+        "recursive_mkdir_rel_2: Making: {} in cwd {} [{}]",
+        path.display(),
+        cwd.display(),
+        path.exists()
+    );
+    t!(fs::create_dir_all(&path));
+    assert!(path.is_dir());
+    assert!(path.parent().unwrap().is_dir());
+    let path2 = Path::new("quux/blat");
+    println!(
+        "recursive_mkdir_rel_2: Making: {} in cwd {}",
+        path2.display(),
+        cwd.display()
+    );
+    t!(fs::create_dir("quux"));
+    t!(fs::create_dir_all(&path2));
+    assert!(path2.is_dir());
+    assert!(path2.parent().unwrap().is_dir());
+}
+
+// Ideally this would be in core, but needs TempFile
+pub fn test_remove_dir_all_ok() {
+    let tmpdir = t!(TempDir::new());
+    let tmpdir = tmpdir.path();
+    let root = tmpdir.join("foo");
+
+    println!("making {}", root.display());
+    t!(fs::create_dir(&root));
+    t!(fs::create_dir(&root.join("foo")));
+    t!(fs::create_dir(&root.join("foo").join("bar")));
+    t!(fs::create_dir(&root.join("foo").join("bar").join("blat")));
+    t!(fs::remove_dir_all(&root));
+    assert!(!root.exists());
+    assert!(!root.join("bar").exists());
+    assert!(!root.join("bar").join("blat").exists());
+}
+
+pub fn dont_double_panic() {
     let r: Result<(), _> = thread::spawn(move || {
         let tmpdir = TempDir::new().unwrap();
         // Remove the temporary directory so that TempDir sees
         // an error on drop
-        fs::remove_dir(tmpdir.path()).unwrap();
+        t!(fs::remove_dir(tmpdir.path()));
         // Panic. If TempDir panics *again* due to the rmdir
         // error then the process will abort.
         panic!();
@@ -147,14 +231,14 @@
 where
     F: FnOnce(),
 {
-    let tmpdir = TempDir::new().unwrap();
-    assert!(std::env::set_current_dir(tmpdir.path()).is_ok());
+    let tmpdir = t!(TempDir::new());
+    assert!(env::set_current_dir(tmpdir.path()).is_ok());
 
     f();
 }
 
-fn pass_as_asref_path() {
-    let tempdir = TempDir::new().unwrap();
+pub fn pass_as_asref_path() {
+    let tempdir = t!(TempDir::new());
     takes_asref_path(&tempdir);
 
     fn takes_asref_path<T: AsRef<Path>>(path: T) {
@@ -163,22 +247,15 @@
     }
 }
 
-fn test_keep() {
-    let tmpdir = Builder::new().keep(true).tempdir().unwrap();
-    let path = tmpdir.path().to_owned();
-    drop(tmpdir);
-    assert!(path.exists());
-    fs::remove_dir(path).unwrap();
-}
-
 #[test]
 fn main() {
     in_tmpdir(test_tempdir);
-    in_tmpdir(test_prefix);
-    in_tmpdir(test_customnamed);
     in_tmpdir(test_rm_tempdir);
     in_tmpdir(test_rm_tempdir_close);
+    in_tmpdir(recursive_mkdir_rel);
+    in_tmpdir(recursive_mkdir_dot);
+    in_tmpdir(recursive_mkdir_rel_2);
+    in_tmpdir(test_remove_dir_all_ok);
     in_tmpdir(dont_double_panic);
     in_tmpdir(pass_as_asref_path);
-    in_tmpdir(test_keep);
 }
diff --git a/crates/tempfile/tests/tempfile.rs b/crates/tempfile/tests/tempfile.rs
index c2f6844..f4dddb2 100644
--- a/crates/tempfile/tests/tempfile.rs
+++ b/crates/tempfile/tests/tempfile.rs
@@ -2,11 +2,8 @@
 
 use std::fs;
 use std::io::{Read, Seek, SeekFrom, Write};
-#[cfg(target_os = "linux")]
-use std::{
-    sync::mpsc::{sync_channel, TryRecvError},
-    thread,
-};
+use std::sync::mpsc::{sync_channel, TryRecvError};
+use std::thread;
 
 #[test]
 fn test_basic() {