Coverage Report

Created: 2024-08-22 06:13

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