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