URL: https://docs.rs/tempfile/latest/src/tempfile/util.rs.html
Content-Type: text/html
Method: native

---

---
meta-description: Source of the Rust file `src/util.rs`.
meta-generator: rustdoc
meta-viewport: width=device-width, initial-scale=1.0
title: util.rs - source
---

[Docs.rs](/)

- [tempfile-3.27.0](# "A library for managing temporary files and directories.")

  - tempfile 3.27.0
  - [Permalink](/tempfile/3.27.0/src/tempfile/util.rs.html "Get a link to this specific version")
  - [Docs.rs crate page](/crate/tempfile/latest "See tempfile in docs.rs")
  - [MIT](https://spdx.org/licenses/MIT) OR [Apache-2.0](https://spdx.org/licenses/Apache-2.0)
  - 28 June 2026
  

  - Links
  - [Homepage](https://stebalien.com/projects/tempfile-rs/)
  - [Repository](https://github.com/Stebalien/tempfile)
  - [crates.io](https://crates.io/crates/tempfile "See tempfile in crates.io")
  - [Source](/crate/tempfile/latest/source/ "Browse source of tempfile-3.27.0")

  - Owners
  - [Stebalien](https://crates.io/users/Stebalien)
  

  - Dependencies
  -     - [fastrand ^2.1.1 *normal*](/fastrand/^2.1.1/)
    - [once_cell ^1.19.0 *normal*](/once_cell/^1.19.0/)
    - [doc-comment ^0.3 *dev*](/doc-comment/^0.3/)
    - [rustix ^1.1.4 *normal*](/rustix/^1.1.4/)
    - [getrandom >=0.3.0, <0.5 *normal* *optional*](/getrandom/%3E=0.3.0,%20%3C0.5/)
    - [windows-sys >=0.52, <0.62 *normal*](/windows-sys/%3E=0.52,%20%3C0.62/)

  - Versions
  -

  

  - [**92.11%** of the crate is documented](/crate/tempfile/latest)

- [Platform](#)
  - [x86_64-unknown-linux-gnu](/crate/tempfile/latest/target-redirect/src/tempfile/util.rs.html)
- [Feature flags](/crate/tempfile/latest/features "Browse available feature flags of tempfile-3.27.0")

- [docs.rs](#)
  - [About docs.rs](/about)
  - [Badges](/about/badges)
  - [Builds](/about/builds)
  - [Metadata](/about/metadata)
  - [Shorthand URLs](/about/redirections)
  - [Download](/about/download)
  - [Rustdoc JSON](/about/rustdoc-json)
  - [Build queue](/releases/queue)
  - [Privacy policy](https://foundation.rust-lang.org/policies/privacy-policy/#docs.rs)

- [Rust](#)
  - [Rust website](https://www.rust-lang.org/)
  - [The Book](https://doc.rust-lang.org/book/)
  - [Standard Library API Reference](https://doc.rust-lang.org/std/)
  - [Rust by Example](https://doc.rust-lang.org/rust-by-example/)
  - [The Cargo Guide](https://doc.rust-lang.org/cargo/guide/)
  - [Clippy Documentation](https://doc.rust-lang.org/nightly/clippy)

[/-/storage-change-detection.html](/-/storage-change-detection.html)

[Skip to main content](#main-content)

# tempfile/util.rs

    [1](#1)use std::ffi::{[OsStr](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsStr.html), [OsString](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsString.html)};
    [2](#2)use std::path::{[Path](https://doc.rust-lang.org/nightly/std/path/struct.Path.html), [PathBuf](https://doc.rust-lang.org/nightly/std/path/struct.PathBuf.html)};
    [3](#3)use std::{[io](https://doc.rust-lang.org/nightly/std/io/index.html), [iter::repeat_with](https://doc.rust-lang.org/nightly/core/iter/sources/repeat_with/fn.repeat_with.html)};
    [4](#4)
    [5](#5)use [crate::error::IoResultExt](error.rs.html#22-27);
    [6](#6)
    [7](#7)fn tmpname(rng: &mut fastrand::[Rng](https://docs.rs/fastrand/2.3.0/x86_64-unknown-linux-gnu/fastrand/struct.Rng.html), prefix: &[OsStr](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsStr.html), suffix: &[OsStr](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsStr.html), rand_len: [usize](https://doc.rust-lang.org/nightly/std/primitive.usize.html)) -> [OsString](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsString.html) {
    [8](#8)    let capacity = [prefix](#7)
    [9](#9)        .[len](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsStr.html#method.len)()
    [10](#10)        .[saturating_add](https://doc.rust-lang.org/nightly/core/primitive.usize.html#method.saturating_add)([suffix](#7).[len](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsStr.html#method.len)())
    [11](#11)        .[saturating_add](https://doc.rust-lang.org/nightly/core/primitive.usize.html#method.saturating_add)([rand_len](#7));
    [12](#12)    let mut buf = [OsString](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsString.html)::[with_capacity](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsString.html#method.with_capacity)([capacity](#8));
    [13](#13)    [buf](#12).[push](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsString.html#method.push)([prefix](#7));
    [14](#14)    let mut char_buf = [0u8; 4];
    [15](#15)    for c in repeat_with(|| rng.alphanumeric()).take(rand_len) {
    [16](#16)        buf.push(c.encode_utf8(&mut char_buf));
    [17](#17)    }
    [18](#18)    [buf](#12).[push](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsString.html#method.push)([suffix](#7));
    [19](#19)    [buf](#12)
    [20](#20)}
    [21](#21)
    [22](#22)pub fn create_helper<R>(
    [23](#23)    base: &[Path](https://doc.rust-lang.org/nightly/std/path/struct.Path.html),
    [24](#24)    prefix: &[OsStr](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsStr.html),
    [25](#25)    suffix: &[OsStr](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.OsStr.html),
    [26](#26)    random_len: [usize](https://doc.rust-lang.org/nightly/std/primitive.usize.html),
    [27](#27)    mut f: impl [FnMut](https://doc.rust-lang.org/nightly/core/ops/function/trait.FnMut.html)([PathBuf](https://doc.rust-lang.org/nightly/std/path/struct.PathBuf.html)) -> io::[Result](https://doc.rust-lang.org/nightly/std/io/error/type.Result.html)<R>,
    [28](#28)) -> io::[Result](https://doc.rust-lang.org/nightly/std/io/error/type.Result.html)<R> {
    [29](#29)    // Make the path absolute. Otherwise, changing the current directory can invalidate a stored
    [30](#30)    // path (causing issues when cleaning up temporary files).
    [31](#31)    let mut base = [base](#23); // re-borrow to shrink lifetime
    [32](#32)    let base_path_storage; // slot to store the absolute path, if necessary.
    [33](#33)    if ![base](#31).[is_absolute](https://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.is_absolute)() {
    [34](#34)        let cur_dir = std::env::current_dir()?;
    [35](#35)        [base_path_storage](#32) = [cur_dir](#34).[join](https://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.join)([base](#31));
    [36](#36)        [base](#31) = &[base_path_storage](#32);
    [37](#37)    }
    [38](#38)
    [39](#39)    let num_retries = if [random_len](#26) != 0 {
    [40](#40)        crate::[NUM_RETRIES](lib.rs.html#194)
    [41](#41)    } else {
    [42](#42)        1
    [43](#43)    };
    [44](#44)
    [45](#45)    // We fork the fastrand rng.
    [46](#46)    let mut rng = fastrand::[Rng](https://docs.rs/fastrand/2.3.0/x86_64-unknown-linux-gnu/fastrand/struct.Rng.html)::[new](https://docs.rs/fastrand/2.3.0/x86_64-unknown-linux-gnu/fastrand/struct.Rng.html#method.new)();
    [47](#47)    for i in 0..num_retries {
    [48](#48)        // If we fail to create the file the first three times, re-seed from system randomness in
    [49](#49)        // case an attacker is predicting our randomness (fastrand is predictable). If re-seeding
    [50](#50)        // doesn't help, either:
    [51](#51)        //
    [52](#52)        // 1. We have lots of temporary files, possibly created by an attacker but not necessarily.
    [53](#53)        //    Re-seeding the randomness won't help here.
    [54](#54)        // 2. We're failing to create random files for some other reason. This shouldn't be the case
    [55](#55)        //    given that we're checking error kinds, but it could happen.
    [56](#56)        #[cfg(all(
    [57](#57)            feature = "getrandom",
    [58](#58)            any(windows, unix, target_os = "redox", target_os = "wasi")
    [59](#59)        ))]
    [60](#60)        if i == 3 {
    [61](#61)            if let Ok(seed) = getrandom::u64() {
    [62](#62)                rng.seed(seed);
    [63](#63)            }
    [64](#64)        }
    [65](#65)        let _ = i; // avoid unused variable warning for the above.
    [66](#66)
    [67](#67)        let path = base.join(tmpname(&mut rng, prefix, suffix, random_len));
    [68](#68)        return match f(path) {
    [69](#69)            Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists && num_retries > 1 => continue,
    [70](#70)            // AddrInUse can happen if we're creating a UNIX domain socket and
    [71](#71)            // the path already exists.
    [72](#72)            Err(ref e) if e.kind() == io::ErrorKind::AddrInUse && num_retries > 1 => continue,
    [73](#73)            res => res,
    [74](#74)        };
    [75](#75)    }
    [76](#76)
    [77](#77)    [Err](https://doc.rust-lang.org/nightly/core/result/enum.Result.html#variant.Err)(io::[Error](https://doc.rust-lang.org/nightly/std/io/error/struct.Error.html)::[new](https://doc.rust-lang.org/nightly/std/io/error/struct.Error.html#method.new)(
    [78](#78)        io::ErrorKind::[AlreadyExists](https://doc.rust-lang.org/nightly/core/io/error/enum.ErrorKind.html#variant.AlreadyExists),
    [79](#79)        "too many temporary files exist",
    [80](#80)    ))
    [81](#81)    .[with_err_path](error.rs.html#23-26)(|| [base](#31))
    [82](#82)}