tempfile/
lib.rs

1//! Temporary files and directories.
2//!
3//! - Use the [`tempfile()`] function for temporary files
4//! - Use the [`tempdir()`] function for temporary directories.
5//!
6//! # Design
7//!
8//! This crate provides several approaches to creating temporary files and directories.
9//! [`tempfile()`] relies on the OS to remove the temporary file once the last handle is closed.
10//! [`TempDir`] and [`NamedTempFile`] both rely on Rust destructors for cleanup.
11//!
12//! When choosing between the temporary file variants, prefer `tempfile`
13//! unless you either need to know the file's path or to be able to persist it.
14//!
15//! ## Resource Leaking
16//!
17//! `tempfile` will (almost) never fail to cleanup temporary resources. However `TempDir` and
18//! `NamedTempFile` will fail if their destructors don't run. This is because `tempfile` relies on
19//! the OS to cleanup the underlying file, while `TempDir` and `NamedTempFile` rely on rust
20//! destructors to do so. Destructors may fail to run if the process exits through an unhandled
21//! signal interrupt (like `SIGINT`), or if the instance is declared statically (like with
22//! [`lazy_static`]), among other possible reasons.
23//!
24//! ## Unexpected File Deletion
25//!
26//! Most operating systems periodically clean up temporary files that haven't been accessed recently
27//! (often on the order of multiple days). This issue does not affect unnamed temporary files but
28//! can invalidate the paths associated with named temporary files on Unix-like systems because the
29//! temporary file can be unlinked from the filesystem while still open and in-use. See the
30//! [temporary file cleaner](#temporary-file-cleaners) section for more security implications.
31//!
32//! ## Security
33//!
34//! This section discusses security issues relevant to Unix-like operating systems that use shared
35//! temporary directories by default. Importantly, it's not relevant for Windows or macOS as both
36//! operating systems use private per-user temporary directories by default.
37//!
38//! Applications can mitigate the issues described below by using [`env::override_temp_dir`] to
39//! change the default temporary directory but should do so if and only if default the temporary
40//! directory ([`env::temp_dir`]) is unsuitable (is world readable, world writable, managed by a
41//! temporary file cleaner, etc.).
42//!
43//! ### Temporary File Cleaners
44//!
45//! In the presence of pathological temporary file cleaner, relying on file paths is unsafe because
46//! a temporary file cleaner could delete the temporary file which an attacker could then replace.
47//!
48//! This isn't an issue for [`tempfile`] as it doesn't rely on file paths. However, [`NamedTempFile`]
49//! and temporary directories _do_ rely on file paths for _some_ operations. See the security
50//! documentation on the [`NamedTempFile`] and the [`TempDir`] types for more information.
51//!
52//! Mitigation:
53//!
54//! - This is rarely an issue for short-lived files as temporary file cleaners usually only remove
55//!   temporary files that haven't been modified or accessed within many (10-30) days.
56//! - Very long lived temporary files should be placed in directories not managed by temporary file
57//!   cleaners.
58//!
59//! ### Access Permissions
60//!
61//! Temporary _files_ created with this library are private by default on all operating systems.
62//! However, temporary _directories_ are created with the default permissions and will therefore be
63//! world-readable by default unless the user has changed their umask and/or default temporary
64//! directory.
65//!
66//! ### Denial of Service
67//!
68//! If the file-name randomness ([`Builder::rand_bytes`]) is too small and/or this crate is built
69//! without the `getrandom` feature, it may be possible for an attacker to predict the random file
70//! names chosen by this library, preventing temporary file creation by creating temporary files
71//! with these predicted file names. By default, this library mitigates this denial of service
72//! attack by:
73//!
74//! 1. Defaulting to 6 random characters per temporary file forcing an attacker to create billions
75//!    of files before random collisions are expected (at which point you probably have larger
76//!    problems).
77//! 2. Re-seeding the random filename generator from system randomness after 3 failed attempts to
78//!    create temporary a file (when the `getrandom` feature is enabled as it is by default on all
79//!    major platforms).
80//!
81//! ## Early drop pitfall
82//!
83//! Because `TempDir` and `NamedTempFile` rely on their destructors for cleanup, this can lead
84//! to an unexpected early removal of the directory/file, usually when working with APIs which are
85//! generic over `AsRef<Path>`. Consider the following example:
86//!
87//! ```no_run
88//! use tempfile::tempdir;
89//! use std::process::Command;
90//!
91//! // Create a directory inside of `env::temp_dir()`.
92//! let temp_dir = tempdir()?;
93//!
94//! // Spawn the `touch` command inside the temporary directory and collect the exit status
95//! // Note that `temp_dir` is **not** moved into `current_dir`, but passed as a reference
96//! let exit_status = Command::new("touch").arg("tmp").current_dir(&temp_dir).status()?;
97//! assert!(exit_status.success());
98//!
99//! # Ok::<(), std::io::Error>(())
100//! ```
101//!
102//! This works because a reference to `temp_dir` is passed to `current_dir`, resulting in the
103//! destructor of `temp_dir` being run after the `Command` has finished execution. Moving the
104//! `TempDir` into the `current_dir` call would result in the `TempDir` being converted into
105//! an internal representation, with the original value being dropped and the directory thus
106//! being deleted, before the command can be executed.
107//!
108//! The `touch` command would fail with an `No such file or directory` error.
109//!
110//! ## Examples
111//!
112//! Create a temporary file and write some data into it:
113//!
114//! ```
115//! use tempfile::tempfile;
116//! use std::io::Write;
117//!
118//! // Create a file inside of `env::temp_dir()`.
119//! let mut file = tempfile()?;
120//!
121//! writeln!(file, "Brian was here. Briefly.")?;
122//! # Ok::<(), std::io::Error>(())
123//! ```
124//!
125//! Create a named temporary file and open an independent file handle:
126//!
127//! ```
128//! use tempfile::NamedTempFile;
129//! use std::io::{Write, Read};
130//!
131//! let text = "Brian was here. Briefly.";
132//!
133//! // Create a file inside of `env::temp_dir()`.
134//! let mut file1 = NamedTempFile::new()?;
135//!
136//! // Re-open it.
137//! let mut file2 = file1.reopen()?;
138//!
139//! // Write some test data to the first handle.
140//! file1.write_all(text.as_bytes())?;
141//!
142//! // Read the test data using the second handle.
143//! let mut buf = String::new();
144//! file2.read_to_string(&mut buf)?;
145//! assert_eq!(buf, text);
146//! # Ok::<(), std::io::Error>(())
147//! ```
148//!
149//! Create a temporary directory and add a file to it:
150//!
151//! ```
152//! use tempfile::tempdir;
153//! use std::fs::File;
154//! use std::io::Write;
155//!
156//! // Create a directory inside of `env::temp_dir()`.
157//! let dir = tempdir()?;
158//!
159//! let file_path = dir.path().join("my-temporary-note.txt");
160//! let mut file = File::create(file_path)?;
161//! writeln!(file, "Brian was here. Briefly.")?;
162//!
163//! // By closing the `TempDir` explicitly, we can check that it has
164//! // been deleted successfully. If we don't close it explicitly,
165//! // the directory will still be deleted when `dir` goes out
166//! // of scope, but we won't know whether deleting the directory
167//! // succeeded.
168//! drop(file);
169//! dir.close()?;
170//! # Ok::<(), std::io::Error>(())
171//! ```
172//!
173//! [`tempfile()`]: fn.tempfile.html
174//! [`tempdir()`]: fn.tempdir.html
175//! [`TempDir`]: struct.TempDir.html
176//! [`NamedTempFile`]: struct.NamedTempFile.html
177//! [`lazy_static`]: https://github.com/rust-lang-nursery/lazy-static.rs/issues/62
178
179#![doc(
180    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
181    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
182    html_root_url = "https://docs.rs/tempfile/latest"
183)]
184#![cfg_attr(test, deny(warnings))]
185#![deny(rust_2018_idioms)]
186#![allow(clippy::redundant_field_names)]
187// wasip2 conditionally gates stdlib APIs.
188// https://github.com/rust-lang/rust/issues/130323
189#![cfg_attr(
190    all(feature = "nightly", target_os = "wasi", target_env = "p2"),
191    feature(wasip2)
192)]
193#![cfg_attr(all(feature = "nightly", target_os = "wasi"), feature(wasi_ext))]
194
195#[cfg(doctest)]
196doc_comment::doctest!("../README.md");
197
198const NUM_RETRIES: u32 = 65536;
199const NUM_RAND_CHARS: usize = 6;
200
201use std::ffi::OsStr;
202use std::fs::OpenOptions;
203use std::io;
204use std::path::Path;
205
206mod dir;
207mod error;
208mod file;
209mod spooled;
210mod util;
211
212pub mod env;
213
214pub use crate::dir::{tempdir, tempdir_in, TempDir};
215pub use crate::file::{
216    tempfile, tempfile_in, NamedTempFile, PathPersistError, PersistError, TempPath,
217};
218pub use crate::spooled::{spooled_tempfile, SpooledData, SpooledTempFile};
219
220/// Create a new temporary file or directory with custom options.
221#[derive(Debug, Clone, Eq, PartialEq)]
222pub struct Builder<'a, 'b> {
223    random_len: usize,
224    prefix: &'a OsStr,
225    suffix: &'b OsStr,
226    append: bool,
227    permissions: Option<std::fs::Permissions>,
228    keep: bool,
229}
230
231impl Default for Builder<'_, '_> {
232    fn default() -> Self {
233        Builder {
234            random_len: crate::NUM_RAND_CHARS,
235            prefix: OsStr::new(".tmp"),
236            suffix: OsStr::new(""),
237            append: false,
238            permissions: None,
239            keep: false,
240        }
241    }
242}
243
244impl<'a, 'b> Builder<'a, 'b> {
245    /// Create a new `Builder`.
246    ///
247    /// # Examples
248    ///
249    /// Create a named temporary file and write some data into it:
250    ///
251    /// ```
252    /// use std::ffi::OsStr;
253    /// use tempfile::Builder;
254    ///
255    /// let named_tempfile = Builder::new()
256    ///     .prefix("my-temporary-note")
257    ///     .suffix(".txt")
258    ///     .rand_bytes(5)
259    ///     .tempfile()?;
260    ///
261    /// let name = named_tempfile
262    ///     .path()
263    ///     .file_name().and_then(OsStr::to_str);
264    ///
265    /// if let Some(name) = name {
266    ///     assert!(name.starts_with("my-temporary-note"));
267    ///     assert!(name.ends_with(".txt"));
268    ///     assert_eq!(name.len(), "my-temporary-note.txt".len() + 5);
269    /// }
270    /// # Ok::<(), std::io::Error>(())
271    /// ```
272    ///
273    /// Create a temporary directory and add a file to it:
274    ///
275    /// ```
276    /// use std::io::Write;
277    /// use std::fs::File;
278    /// use std::ffi::OsStr;
279    /// use tempfile::Builder;
280    ///
281    /// let dir = Builder::new()
282    ///     .prefix("my-temporary-dir")
283    ///     .rand_bytes(5)
284    ///     .tempdir()?;
285    ///
286    /// let file_path = dir.path().join("my-temporary-note.txt");
287    /// let mut file = File::create(file_path)?;
288    /// writeln!(file, "Brian was here. Briefly.")?;
289    ///
290    /// // By closing the `TempDir` explicitly, we can check that it has
291    /// // been deleted successfully. If we don't close it explicitly,
292    /// // the directory will still be deleted when `dir` goes out
293    /// // of scope, but we won't know whether deleting the directory
294    /// // succeeded.
295    /// drop(file);
296    /// dir.close()?;
297    /// # Ok::<(), std::io::Error>(())
298    /// ```
299    ///
300    /// Create a temporary directory with a chosen prefix under a chosen folder:
301    ///
302    /// ```no_run
303    /// use tempfile::Builder;
304    ///
305    /// let dir = Builder::new()
306    ///     .prefix("my-temporary-dir")
307    ///     .tempdir_in("folder-with-tempdirs")?;
308    /// # Ok::<(), std::io::Error>(())
309    /// ```
310    #[must_use]
311    pub fn new() -> Self {
312        Self::default()
313    }
314
315    /// Set a custom filename prefix.
316    ///
317    /// Path separators are legal but not advisable.
318    /// Default: `.tmp`.
319    ///
320    /// # Examples
321    ///
322    /// ```
323    /// use tempfile::Builder;
324    ///
325    /// let named_tempfile = Builder::new()
326    ///     .prefix("my-temporary-note")
327    ///     .tempfile()?;
328    /// # Ok::<(), std::io::Error>(())
329    /// ```
330    pub fn prefix<S: AsRef<OsStr> + ?Sized>(&mut self, prefix: &'a S) -> &mut Self {
331        self.prefix = prefix.as_ref();
332        self
333    }
334
335    /// Set a custom filename suffix.
336    ///
337    /// Path separators are legal but not advisable.
338    /// Default: empty.
339    ///
340    /// # Examples
341    ///
342    /// ```
343    /// use tempfile::Builder;
344    ///
345    /// let named_tempfile = Builder::new()
346    ///     .suffix(".txt")
347    ///     .tempfile()?;
348    /// # Ok::<(), std::io::Error>(())
349    /// ```
350    pub fn suffix<S: AsRef<OsStr> + ?Sized>(&mut self, suffix: &'b S) -> &mut Self {
351        self.suffix = suffix.as_ref();
352        self
353    }
354
355    /// Set the number of random bytes.
356    ///
357    /// Default: `6`.
358    ///
359    /// # Examples
360    ///
361    /// ```
362    /// use tempfile::Builder;
363    ///
364    /// let named_tempfile = Builder::new()
365    ///     .rand_bytes(5)
366    ///     .tempfile()?;
367    /// # Ok::<(), std::io::Error>(())
368    /// ```
369    pub fn rand_bytes(&mut self, rand: usize) -> &mut Self {
370        self.random_len = rand;
371        self
372    }
373
374    /// Set the file to be opened in append mode.
375    ///
376    /// Default: `false`.
377    ///
378    /// # Examples
379    ///
380    /// ```
381    /// use tempfile::Builder;
382    ///
383    /// let named_tempfile = Builder::new()
384    ///     .append(true)
385    ///     .tempfile()?;
386    /// # Ok::<(), std::io::Error>(())
387    /// ```
388    pub fn append(&mut self, append: bool) -> &mut Self {
389        self.append = append;
390        self
391    }
392
393    /// The permissions to create the tempfile or [tempdir](Self::tempdir) with.
394    ///
395    /// # Security
396    ///
397    /// By default, the permissions of tempfiles on Unix are set for it to be
398    /// readable and writable by the owner only, yielding the greatest amount
399    /// of security.
400    /// As this method allows to widen the permissions, security would be
401    /// reduced in such cases.
402    ///
403    /// # Platform Notes
404    /// ## Unix
405    ///
406    /// The actual permission bits set on the tempfile or tempdir will be affected by the `umask`
407    /// applied by the underlying syscall. The actual permission bits are calculated via
408    /// `permissions & !umask`.
409    ///
410    /// Permissions default to `0o600` for tempfiles and `0o777` for tempdirs. Note, this doesn't
411    /// include effects of the current `umask`. For example, combined with the standard umask
412    /// `0o022`, the defaults yield `0o600` for tempfiles and `0o755` for tempdirs.
413    ///
414    /// ## Windows and others
415    ///
416    /// This setting is unsupported and trying to set a file or directory read-only
417    /// will return an error.
418    ///
419    /// # Examples
420    ///
421    /// Create a named temporary file that is world-readable.
422    ///
423    /// ```
424    /// # #[cfg(unix)]
425    /// # {
426    /// use tempfile::Builder;
427    /// use std::os::unix::fs::PermissionsExt;
428    ///
429    /// let all_read_write = std::fs::Permissions::from_mode(0o666);
430    /// let tempfile = Builder::new().permissions(all_read_write).tempfile()?;
431    /// let actual_permissions = tempfile.path().metadata()?.permissions();
432    /// assert_ne!(
433    ///     actual_permissions.mode() & !0o170000,
434    ///     0o600,
435    ///     "we get broader permissions than the default despite umask"
436    /// );
437    /// # }
438    /// # Ok::<(), std::io::Error>(())
439    /// ```
440    ///
441    /// Create a named temporary directory that is restricted to the owner.
442    ///
443    /// ```
444    /// # #[cfg(unix)]
445    /// # {
446    /// use tempfile::Builder;
447    /// use std::os::unix::fs::PermissionsExt;
448    ///
449    /// let owner_rwx = std::fs::Permissions::from_mode(0o700);
450    /// let tempdir = Builder::new().permissions(owner_rwx).tempdir()?;
451    /// let actual_permissions = tempdir.path().metadata()?.permissions();
452    /// assert_eq!(
453    ///     actual_permissions.mode() & !0o170000,
454    ///     0o700,
455    ///     "we get the narrow permissions we asked for"
456    /// );
457    /// # }
458    /// # Ok::<(), std::io::Error>(())
459    /// ```
460    pub fn permissions(&mut self, permissions: std::fs::Permissions) -> &mut Self {
461        self.permissions = Some(permissions);
462        self
463    }
464
465    /// Set the file/folder to be kept even when the [`NamedTempFile`]/[`TempDir`] goes out of
466    /// scope.
467    ///
468    /// By default, the file/folder is automatically cleaned up in the destructor of
469    /// [`NamedTempFile`]/[`TempDir`]. When `keep` is set to `true`, this behavior is suppressed.
470    ///
471    /// If you wish to keep a temporary file or directory after creating it, call
472    /// [`NamedTempFile::keep`] or [`TempDir::into_path`] respectively.
473    ///
474    /// # Examples
475    ///
476    /// ```
477    /// use tempfile::Builder;
478    ///
479    /// let named_tempfile = Builder::new()
480    ///     .keep(true)
481    ///     .tempfile()?;
482    /// # Ok::<(), std::io::Error>(())
483    /// ```
484    pub fn keep(&mut self, keep: bool) -> &mut Self {
485        self.keep = keep;
486        self
487    }
488
489    /// Create the named temporary file.
490    ///
491    /// # Security
492    ///
493    /// See [the security][security] docs on `NamedTempFile`.
494    ///
495    /// # Resource leaking
496    ///
497    /// See [the resource leaking][resource-leaking] docs on `NamedTempFile`.
498    ///
499    /// # Errors
500    ///
501    /// If the file cannot be created, `Err` is returned.
502    ///
503    /// # Examples
504    ///
505    /// ```
506    /// use tempfile::Builder;
507    ///
508    /// let tempfile = Builder::new().tempfile()?;
509    /// # Ok::<(), std::io::Error>(())
510    /// ```
511    ///
512    /// [security]: struct.NamedTempFile.html#security
513    /// [resource-leaking]: struct.NamedTempFile.html#resource-leaking
514    pub fn tempfile(&self) -> io::Result<NamedTempFile> {
515        self.tempfile_in(env::temp_dir())
516    }
517
518    /// Create the named temporary file in the specified directory.
519    ///
520    /// # Security
521    ///
522    /// See [the security][security] docs on `NamedTempFile`.
523    ///
524    /// # Resource leaking
525    ///
526    /// See [the resource leaking][resource-leaking] docs on `NamedTempFile`.
527    ///
528    /// # Errors
529    ///
530    /// If the file cannot be created, `Err` is returned.
531    ///
532    /// # Examples
533    ///
534    /// ```
535    /// use tempfile::Builder;
536    ///
537    /// let tempfile = Builder::new().tempfile_in("./")?;
538    /// # Ok::<(), std::io::Error>(())
539    /// ```
540    ///
541    /// [security]: struct.NamedTempFile.html#security
542    /// [resource-leaking]: struct.NamedTempFile.html#resource-leaking
543    pub fn tempfile_in<P: AsRef<Path>>(&self, dir: P) -> io::Result<NamedTempFile> {
544        util::create_helper(
545            dir.as_ref(),
546            self.prefix,
547            self.suffix,
548            self.random_len,
549            |path| {
550                file::create_named(
551                    path,
552                    OpenOptions::new().append(self.append),
553                    self.permissions.as_ref(),
554                    self.keep,
555                )
556            },
557        )
558    }
559
560    /// Attempts to make a temporary directory inside of [`env::temp_dir()`] whose
561    /// name will have the prefix, `prefix`. The directory and
562    /// everything inside it will be automatically deleted once the
563    /// returned `TempDir` is destroyed.
564    ///
565    /// # Resource leaking
566    ///
567    /// See [the resource leaking][resource-leaking] docs on `TempDir`.
568    ///
569    /// # Errors
570    ///
571    /// If the directory can not be created, `Err` is returned.
572    ///
573    /// # Examples
574    ///
575    /// ```
576    /// use tempfile::Builder;
577    ///
578    /// let tmp_dir = Builder::new().tempdir()?;
579    /// # Ok::<(), std::io::Error>(())
580    /// ```
581    ///
582    /// [resource-leaking]: struct.TempDir.html#resource-leaking
583    pub fn tempdir(&self) -> io::Result<TempDir> {
584        self.tempdir_in(env::temp_dir())
585    }
586
587    /// Attempts to make a temporary directory inside of `dir`.
588    /// The directory and everything inside it will be automatically
589    /// deleted once the returned `TempDir` is destroyed.
590    ///
591    /// # Resource leaking
592    ///
593    /// See [the resource leaking][resource-leaking] docs on `TempDir`.
594    ///
595    /// # Errors
596    ///
597    /// If the directory can not be created, `Err` is returned.
598    ///
599    /// # Examples
600    ///
601    /// ```
602    /// use tempfile::Builder;
603    ///
604    /// let tmp_dir = Builder::new().tempdir_in("./")?;
605    /// # Ok::<(), std::io::Error>(())
606    /// ```
607    ///
608    /// [resource-leaking]: struct.TempDir.html#resource-leaking
609    pub fn tempdir_in<P: AsRef<Path>>(&self, dir: P) -> io::Result<TempDir> {
610        util::create_helper(
611            dir.as_ref(),
612            self.prefix,
613            self.suffix,
614            self.random_len,
615            |path| dir::create(path, self.permissions.as_ref(), self.keep),
616        )
617    }
618
619    /// Attempts to create a temporary file (or file-like object) using the
620    /// provided closure. The closure is passed a temporary file path and
621    /// returns an [`std::io::Result`]. The path provided to the closure will be
622    /// inside of [`env::temp_dir()`]. Use [`Builder::make_in`] to provide
623    /// a custom temporary directory. If the closure returns one of the
624    /// following errors, then another randomized file path is tried:
625    ///  - [`std::io::ErrorKind::AlreadyExists`]
626    ///  - [`std::io::ErrorKind::AddrInUse`]
627    ///
628    /// This can be helpful for taking full control over the file creation, but
629    /// leaving the temporary file path construction up to the library. This
630    /// also enables creating a temporary UNIX domain socket, since it is not
631    /// possible to bind to a socket that already exists.
632    ///
633    /// Note that [`Builder::append`] is ignored when using [`Builder::make`].
634    ///
635    /// # Security
636    ///
637    /// This has the same [security implications][security] as
638    /// [`NamedTempFile`], but with additional caveats. Specifically, it is up
639    /// to the closure to ensure that the file does not exist and that such a
640    /// check is *atomic*. Otherwise, a [time-of-check to time-of-use
641    /// bug][TOCTOU] could be introduced.
642    ///
643    /// For example, the following is **not** secure:
644    ///
645    /// ```
646    /// use std::fs::File;
647    /// use tempfile::Builder;
648    ///
649    /// // This is NOT secure!
650    /// let tempfile = Builder::new().make(|path| {
651    ///     if path.is_file() {
652    ///         return Err(std::io::ErrorKind::AlreadyExists.into());
653    ///     }
654    ///
655    ///     // Between the check above and the usage below, an attacker could
656    ///     // have replaced `path` with another file, which would get truncated
657    ///     // by `File::create`.
658    ///
659    ///     File::create(path)
660    /// })?;
661    /// # Ok::<(), std::io::Error>(())
662    /// ```
663    ///
664    /// Note that simply using [`std::fs::File::create`] alone is not correct
665    /// because it does not fail if the file already exists:
666    ///
667    /// ```
668    /// use tempfile::Builder;
669    /// use std::fs::File;
670    ///
671    /// // This could overwrite an existing file!
672    /// let tempfile = Builder::new().make(|path| File::create(path))?;
673    /// # Ok::<(), std::io::Error>(())
674    /// ```
675    /// For creating regular temporary files, use [`Builder::tempfile`] instead
676    /// to avoid these problems. This function is meant to enable more exotic
677    /// use-cases.
678    ///
679    /// # Resource leaking
680    ///
681    /// See [the resource leaking][resource-leaking] docs on `NamedTempFile`.
682    ///
683    /// # Errors
684    ///
685    /// If the closure returns any error besides
686    /// [`std::io::ErrorKind::AlreadyExists`] or
687    /// [`std::io::ErrorKind::AddrInUse`], then `Err` is returned.
688    ///
689    /// # Examples
690    /// ```
691    /// # #[cfg(unix)]
692    /// # {
693    /// use std::os::unix::net::UnixListener;
694    /// use tempfile::Builder;
695    ///
696    /// let tempsock = Builder::new().make(|path| UnixListener::bind(path))?;
697    /// # }
698    /// # Ok::<(), std::io::Error>(())
699    /// ```
700    ///
701    /// [TOCTOU]: https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use
702    /// [security]: struct.NamedTempFile.html#security
703    /// [resource-leaking]: struct.NamedTempFile.html#resource-leaking
704    pub fn make<F, R>(&self, f: F) -> io::Result<NamedTempFile<R>>
705    where
706        F: FnMut(&Path) -> io::Result<R>,
707    {
708        self.make_in(env::temp_dir(), f)
709    }
710
711    /// This is the same as [`Builder::make`], except `dir` is used as the base
712    /// directory for the temporary file path.
713    ///
714    /// See [`Builder::make`] for more details and security implications.
715    ///
716    /// # Examples
717    /// ```
718    /// # #[cfg(unix)]
719    /// # {
720    /// use tempfile::Builder;
721    /// use std::os::unix::net::UnixListener;
722    ///
723    /// let tempsock = Builder::new().make_in("./", |path| UnixListener::bind(path))?;
724    /// # }
725    /// # Ok::<(), std::io::Error>(())
726    /// ```
727    pub fn make_in<F, R, P>(&self, dir: P, mut f: F) -> io::Result<NamedTempFile<R>>
728    where
729        F: FnMut(&Path) -> io::Result<R>,
730        P: AsRef<Path>,
731    {
732        util::create_helper(
733            dir.as_ref(),
734            self.prefix,
735            self.suffix,
736            self.random_len,
737            move |path| {
738                Ok(NamedTempFile::from_parts(
739                    f(&path)?,
740                    TempPath::new(path, self.keep),
741                ))
742            },
743        )
744    }
745}