]> git.proxmox.com Git - cargo.git/blob - vendor/tempfile/src/file/mod.rs
New upstream version 0.35.0
[cargo.git] / vendor / tempfile / src / file / mod.rs
1 use std;
2 use std::env;
3 use std::error;
4 use std::ffi::OsStr;
5 use std::fmt;
6 use std::fs::{self, File};
7 use std::io::{self, Read, Seek, SeekFrom, Write};
8 use std::mem;
9 use std::ops::Deref;
10 use std::path::{Path, PathBuf};
11
12 use error::IoResultExt;
13 use Builder;
14
15 mod imp;
16
17 /// Create a new temporary file.
18 ///
19 /// The file will be created in the location returned by [`std::env::temp_dir()`].
20 ///
21 /// # Security
22 ///
23 /// This variant is secure/reliable in the presence of a pathological temporary file cleaner.
24 ///
25 /// # Resource Leaking
26 ///
27 /// The temporary file will be automatically removed by the OS when the last handle to it is closed.
28 /// This doesn't rely on Rust destructors being run, so will (almost) never fail to clean up the temporary file.
29 ///
30 /// # Errors
31 ///
32 /// If the file can not be created, `Err` is returned.
33 ///
34 /// # Examples
35 ///
36 /// ```
37 /// # extern crate tempfile;
38 /// use tempfile::tempfile;
39 /// use std::io::{self, Write};
40 ///
41 /// # fn main() {
42 /// # if let Err(_) = run() {
43 /// # ::std::process::exit(1);
44 /// # }
45 /// # }
46 /// # fn run() -> Result<(), io::Error> {
47 /// // Create a file inside of `std::env::temp_dir()`.
48 /// let mut file = tempfile()?;
49 ///
50 /// writeln!(file, "Brian was here. Briefly.")?;
51 /// # Ok(())
52 /// # }
53 /// ```
54 ///
55 /// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
56 pub fn tempfile() -> io::Result<File> {
57 tempfile_in(&env::temp_dir())
58 }
59
60 /// Create a new temporary file in the specified directory.
61 ///
62 /// # Security
63 ///
64 /// This variant is secure/reliable in the presence of a pathological temporary file cleaner.
65 /// If the temporary file isn't created in [`std::env::temp_dir()`] then temporary file cleaners aren't an issue.
66 ///
67 /// # Resource Leaking
68 ///
69 /// The temporary file will be automatically removed by the OS when the last handle to it is closed.
70 /// This doesn't rely on Rust destructors being run, so will (almost) never fail to clean up the temporary file.
71 ///
72 /// # Errors
73 ///
74 /// If the file can not be created, `Err` is returned.
75 ///
76 /// # Examples
77 ///
78 /// ```
79 /// # extern crate tempfile;
80 /// use tempfile::tempfile_in;
81 /// use std::io::{self, Write};
82 ///
83 /// # fn main() {
84 /// # if let Err(_) = run() {
85 /// # ::std::process::exit(1);
86 /// # }
87 /// # }
88 /// # fn run() -> Result<(), io::Error> {
89 /// // Create a file inside of the current working directory
90 /// let mut file = tempfile_in("./")?;
91 ///
92 /// writeln!(file, "Brian was here. Briefly.")?;
93 /// # Ok(())
94 /// # }
95 /// ```
96 ///
97 /// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
98 pub fn tempfile_in<P: AsRef<Path>>(dir: P) -> io::Result<File> {
99 imp::create(dir.as_ref())
100 }
101
102 /// Error returned when persisting a temporary file path fails.
103 #[derive(Debug)]
104 pub struct PathPersistError {
105 /// The underlying IO error.
106 pub error: io::Error,
107 /// The temporary file path that couldn't be persisted.
108 pub path: TempPath,
109 }
110
111 impl From<PathPersistError> for io::Error {
112 #[inline]
113 fn from(error: PathPersistError) -> io::Error {
114 error.error
115 }
116 }
117
118 impl From<PathPersistError> for TempPath {
119 #[inline]
120 fn from(error: PathPersistError) -> TempPath {
121 error.path
122 }
123 }
124
125 impl fmt::Display for PathPersistError {
126 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127 write!(f, "failed to persist temporary file path: {}", self.error)
128 }
129 }
130
131 impl error::Error for PathPersistError {
132 fn description(&self) -> &str {
133 "failed to persist temporary file path"
134 }
135
136 fn cause(&self) -> Option<&error::Error> {
137 Some(&self.error)
138 }
139 }
140
141 /// A path to a named temporary file without an open file handle.
142 ///
143 /// This is useful when the temporary file needs to be used by a child process,
144 /// for example.
145 ///
146 /// When dropped, the temporary file is deleted.
147 pub struct TempPath {
148 path: PathBuf,
149 }
150
151 impl TempPath {
152 /// Close and remove the temporary file.
153 ///
154 /// Use this if you want to detect errors in deleting the file.
155 ///
156 /// # Errors
157 ///
158 /// If the file cannot be deleted, `Err` is returned.
159 ///
160 /// # Examples
161 ///
162 /// ```no_run
163 /// # extern crate tempfile;
164 /// # use std::io;
165 /// use tempfile::NamedTempFile;
166 ///
167 /// # fn main() {
168 /// # if let Err(_) = run() {
169 /// # ::std::process::exit(1);
170 /// # }
171 /// # }
172 /// # fn run() -> Result<(), io::Error> {
173 /// let file = NamedTempFile::new()?;
174 ///
175 /// // Close the file, but keep the path to it around.
176 /// let path = file.into_temp_path();
177 ///
178 /// // By closing the `TempPath` explicitly, we can check that it has
179 /// // been deleted successfully. If we don't close it explicitly, the
180 /// // file will still be deleted when `file` goes out of scope, but we
181 /// // won't know whether deleting the file succeeded.
182 /// path.close()?;
183 /// # Ok(())
184 /// # }
185 /// ```
186 pub fn close(mut self) -> io::Result<()> {
187 let result = fs::remove_file(&self.path).with_err_path(|| &self.path);
188 mem::replace(&mut self.path, PathBuf::new());
189 mem::forget(self);
190 result
191 }
192
193 /// Persist the temporary file at the target path.
194 ///
195 /// If a file exists at the target path, persist will atomically replace it.
196 /// If this method fails, it will return `self` in the resulting
197 /// [`PathPersistError`].
198 ///
199 /// Note: Temporary files cannot be persisted across filesystems.
200 ///
201 /// # Security
202 ///
203 /// Only use this method if you're positive that a temporary file cleaner
204 /// won't have deleted your file. Otherwise, you might end up persisting an
205 /// attacker controlled file.
206 ///
207 /// # Errors
208 ///
209 /// If the file cannot be moved to the new location, `Err` is returned.
210 ///
211 /// # Examples
212 ///
213 /// ```no_run
214 /// # use std::io::{self, Write};
215 /// # extern crate tempfile;
216 /// use tempfile::NamedTempFile;
217 ///
218 /// # fn main() {
219 /// # if let Err(_) = run() {
220 /// # ::std::process::exit(1);
221 /// # }
222 /// # }
223 /// # fn run() -> Result<(), io::Error> {
224 /// let mut file = NamedTempFile::new()?;
225 /// writeln!(file, "Brian was here. Briefly.")?;
226 ///
227 /// let path = file.into_temp_path();
228 /// path.persist("./saved_file.txt")?;
229 /// # Ok(())
230 /// # }
231 /// ```
232 ///
233 /// [`PathPersistError`]: struct.PathPersistError.html
234 pub fn persist<P: AsRef<Path>>(mut self, new_path: P) -> Result<(), PathPersistError> {
235 match imp::persist(&self.path, new_path.as_ref(), true) {
236 Ok(_) => {
237 // Don't drop `self`. We don't want to try deleting the old
238 // temporary file path. (It'll fail, but the failure is never
239 // seen.)
240 mem::replace(&mut self.path, PathBuf::new());
241 mem::forget(self);
242 Ok(())
243 }
244 Err(e) => Err(PathPersistError {
245 error: e,
246 path: self,
247 }),
248 }
249 }
250
251 /// Persist the temporary file at the target path iff no file exists there.
252 ///
253 /// If a file exists at the target path, fail. If this method fails, it will
254 /// return `self` in the resulting [`PathPersistError`].
255 ///
256 /// Note: Temporary files cannot be persisted across filesystems. Also Note:
257 /// This method is not atomic. It can leave the original link to the
258 /// temporary file behind.
259 ///
260 /// # Security
261 ///
262 /// Only use this method if you're positive that a temporary file cleaner
263 /// won't have deleted your file. Otherwise, you might end up persisting an
264 /// attacker controlled file.
265 ///
266 /// # Errors
267 ///
268 /// If the file cannot be moved to the new location or a file already exists
269 /// there, `Err` is returned.
270 ///
271 /// # Examples
272 ///
273 /// ```no_run
274 /// # use std::io::{self, Write};
275 /// # extern crate tempfile;
276 /// use tempfile::NamedTempFile;
277 ///
278 /// # fn main() {
279 /// # if let Err(_) = run() {
280 /// # ::std::process::exit(1);
281 /// # }
282 /// # }
283 /// # fn run() -> Result<(), io::Error> {
284 /// let mut file = NamedTempFile::new()?;
285 /// writeln!(file, "Brian was here. Briefly.")?;
286 ///
287 /// let path = file.into_temp_path();
288 /// path.persist_noclobber("./saved_file.txt")?;
289 /// # Ok(())
290 /// # }
291 /// ```
292 ///
293 /// [`PathPersistError`]: struct.PathPersistError.html
294 pub fn persist_noclobber<P: AsRef<Path>>(
295 mut self,
296 new_path: P,
297 ) -> Result<(), PathPersistError> {
298 match imp::persist(&self.path, new_path.as_ref(), false) {
299 Ok(_) => {
300 // Don't drop `self`. We don't want to try deleting the old
301 // temporary file path. (It'll fail, but the failure is never
302 // seen.)
303 mem::replace(&mut self.path, PathBuf::new());
304 mem::forget(self);
305 Ok(())
306 }
307 Err(e) => Err(PathPersistError {
308 error: e,
309 path: self,
310 }),
311 }
312 }
313
314 /// Keep the temporary file from being deleted. This function will turn the
315 /// temporary file into a non-temporary file without moving it.
316 ///
317 ///
318 /// # Errors
319 ///
320 /// On some platforms (e.g., Windows), we need to mark the file as
321 /// non-temporary. This operation could fail.
322 ///
323 /// # Examples
324 ///
325 /// ```no_run
326 /// # use std::io::{self, Write};
327 /// # extern crate tempfile;
328 /// use tempfile::NamedTempFile;
329 ///
330 /// # fn main() {
331 /// # if let Err(_) = run() {
332 /// # ::std::process::exit(1);
333 /// # }
334 /// # }
335 /// # fn run() -> Result<(), io::Error> {
336 /// let mut file = NamedTempFile::new()?;
337 /// writeln!(file, "Brian was here. Briefly.")?;
338 ///
339 /// let path = file.into_temp_path();
340 /// let path = path.keep()?;
341 /// # Ok(())
342 /// # }
343 /// ```
344 ///
345 /// [`PathPersistError`]: struct.PathPersistError.html
346 pub fn keep(mut self) -> Result<PathBuf, PathPersistError> {
347 match imp::keep(&self.path) {
348 Ok(_) => {
349 // Don't drop `self`. We don't want to try deleting the old
350 // temporary file path. (It'll fail, but the failure is never
351 // seen.)
352 let mut path = PathBuf::new();
353 mem::swap(&mut self.path, &mut path);
354 mem::forget(self);
355 Ok(path)
356 }
357 Err(e) => Err(PathPersistError {
358 error: e,
359 path: self,
360 }),
361 }
362 }
363 }
364
365 impl fmt::Debug for TempPath {
366 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
367 self.path.fmt(f)
368 }
369 }
370
371 impl Drop for TempPath {
372 fn drop(&mut self) {
373 let _ = fs::remove_file(&self.path);
374 }
375 }
376
377 impl Deref for TempPath {
378 type Target = Path;
379
380 fn deref(&self) -> &Path {
381 &self.path
382 }
383 }
384
385 impl AsRef<Path> for TempPath {
386 fn as_ref(&self) -> &Path {
387 &self.path
388 }
389 }
390
391 impl AsRef<OsStr> for TempPath {
392 fn as_ref(&self) -> &OsStr {
393 self.path.as_os_str()
394 }
395 }
396
397 /// A named temporary file.
398 ///
399 /// The default constructor, [`NamedTempFile::new()`], creates files in
400 /// the location returned by [`std::env::temp_dir()`], but `NamedTempFile`
401 /// can be configured to manage a temporary file in any location
402 /// by constructing with [`NamedTempFile::new_in()`].
403 ///
404 /// # Security
405 ///
406 /// This variant is *NOT* secure/reliable in the presence of a pathological temporary file cleaner.
407 ///
408 /// # Resource Leaking
409 ///
410 /// If the program exits before the `NamedTempFile` destructor is
411 /// run, such as via [`std::process::exit()`], by segfaulting, or by
412 /// receiving a signal like `SIGINT`, then the temporary file
413 /// will not be deleted.
414 ///
415 /// Use the [`tempfile()`] function unless you absolutely need a named file.
416 ///
417 /// [`tempfile()`]: fn.tempfile.html
418 /// [`NamedTempFile::new()`]: #method.new
419 /// [`NamedTempFile::new_in()`]: #method.new_in
420 /// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
421 /// [`std::process::exit()`]: http://doc.rust-lang.org/std/process/fn.exit.html
422 pub struct NamedTempFile {
423 path: TempPath,
424 file: File,
425 }
426
427 impl fmt::Debug for NamedTempFile {
428 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
429 write!(f, "NamedTempFile({:?})", self.path)
430 }
431 }
432
433 impl AsRef<Path> for NamedTempFile {
434 #[inline]
435 fn as_ref(&self) -> &Path {
436 self.path()
437 }
438 }
439
440 /// Error returned when persisting a temporary file fails.
441 #[derive(Debug)]
442 pub struct PersistError {
443 /// The underlying IO error.
444 pub error: io::Error,
445 /// The temporary file that couldn't be persisted.
446 pub file: NamedTempFile,
447 }
448
449 impl From<PersistError> for io::Error {
450 #[inline]
451 fn from(error: PersistError) -> io::Error {
452 error.error
453 }
454 }
455
456 impl From<PersistError> for NamedTempFile {
457 #[inline]
458 fn from(error: PersistError) -> NamedTempFile {
459 error.file
460 }
461 }
462
463 impl fmt::Display for PersistError {
464 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
465 write!(f, "failed to persist temporary file: {}", self.error)
466 }
467 }
468
469 impl error::Error for PersistError {
470 fn description(&self) -> &str {
471 "failed to persist temporary file"
472 }
473 fn cause(&self) -> Option<&error::Error> {
474 Some(&self.error)
475 }
476 }
477
478 impl NamedTempFile {
479 /// Create a new named temporary file.
480 ///
481 /// See [`Builder`] for more configuration.
482 ///
483 /// # Security
484 ///
485 /// This will create a temporary file in the default temporary file
486 /// directory (platform dependent). These directories are often patrolled by temporary file
487 /// cleaners so only use this method if you're *positive* that the temporary file cleaner won't
488 /// delete your file.
489 ///
490 /// Reasons to use this method:
491 ///
492 /// 1. The file has a short lifetime and your temporary file cleaner is
493 /// sane (doesn't delete recently accessed files).
494 ///
495 /// 2. You trust every user on your system (i.e. you are the only user).
496 ///
497 /// 3. You have disabled your system's temporary file cleaner or verified
498 /// that your system doesn't have a temporary file cleaner.
499 ///
500 /// Reasons not to use this method:
501 ///
502 /// 1. You'll fix it later. No you won't.
503 ///
504 /// 2. You don't care about the security of the temporary file. If none of
505 /// the "reasons to use this method" apply, referring to a temporary
506 /// file by name may allow an attacker to create/overwrite your
507 /// non-temporary files. There are exceptions but if you don't already
508 /// know them, don't use this method.
509 ///
510 /// # Errors
511 ///
512 /// If the file can not be created, `Err` is returned.
513 ///
514 /// # Examples
515 ///
516 /// Create a named temporary file and write some data to it:
517 ///
518 /// ```no_run
519 /// # use std::io::{self, Write};
520 /// # extern crate tempfile;
521 /// use tempfile::NamedTempFile;
522 ///
523 /// # fn main() {
524 /// # if let Err(_) = run() {
525 /// # ::std::process::exit(1);
526 /// # }
527 /// # }
528 /// # fn run() -> Result<(), ::std::io::Error> {
529 /// let mut file = NamedTempFile::new()?;
530 ///
531 /// writeln!(file, "Brian was here. Briefly.")?;
532 /// # Ok(())
533 /// # }
534 /// ```
535 ///
536 /// [`Builder`]: struct.Builder.html
537 pub fn new() -> io::Result<NamedTempFile> {
538 Builder::new().tempfile()
539 }
540
541 /// Create a new named temporary file in the specified directory.
542 ///
543 /// See [`NamedTempFile::new()`] for details.
544 ///
545 /// [`NamedTempFile::new()`]: #method.new_in
546 pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<NamedTempFile> {
547 Builder::new().tempfile_in(dir)
548 }
549
550 /// Get the temporary file's path.
551 ///
552 /// # Security
553 ///
554 /// Only use this method if you're positive that a
555 /// temporary file cleaner won't have deleted your file. Otherwise, the path
556 /// returned by this method may refer to an attacker controlled file.
557 ///
558 /// # Examples
559 ///
560 /// ```no_run
561 /// # use std::io::{self, Write};
562 /// # extern crate tempfile;
563 /// use tempfile::NamedTempFile;
564 ///
565 /// # fn main() {
566 /// # if let Err(_) = run() {
567 /// # ::std::process::exit(1);
568 /// # }
569 /// # }
570 /// # fn run() -> Result<(), ::std::io::Error> {
571 /// let file = NamedTempFile::new()?;
572 ///
573 /// println!("{:?}", file.path());
574 /// # Ok(())
575 /// # }
576 /// ```
577 #[inline]
578 pub fn path(&self) -> &Path {
579 &self.path
580 }
581
582 /// Close and remove the temporary file.
583 ///
584 /// Use this if you want to detect errors in deleting the file.
585 ///
586 /// # Errors
587 ///
588 /// If the file cannot be deleted, `Err` is returned.
589 ///
590 /// # Examples
591 ///
592 /// ```no_run
593 /// # extern crate tempfile;
594 /// # use std::io;
595 /// use tempfile::NamedTempFile;
596 ///
597 /// # fn main() {
598 /// # if let Err(_) = run() {
599 /// # ::std::process::exit(1);
600 /// # }
601 /// # }
602 /// # fn run() -> Result<(), io::Error> {
603 /// let file = NamedTempFile::new()?;
604 ///
605 /// // By closing the `NamedTempFile` explicitly, we can check that it has
606 /// // been deleted successfully. If we don't close it explicitly,
607 /// // the file will still be deleted when `file` goes out
608 /// // of scope, but we won't know whether deleting the file
609 /// // succeeded.
610 /// file.close()?;
611 /// # Ok(())
612 /// # }
613 /// ```
614 pub fn close(self) -> io::Result<()> {
615 let NamedTempFile { path, .. } = self;
616 path.close()
617 }
618
619 /// Persist the temporary file at the target path.
620 ///
621 /// If a file exists at the target path, persist will atomically replace it.
622 /// If this method fails, it will return `self` in the resulting
623 /// [`PersistError`].
624 ///
625 /// Note: Temporary files cannot be persisted across filesystems.
626 ///
627 /// # Security
628 ///
629 /// Only use this method if you're positive that a
630 /// temporary file cleaner won't have deleted your file. Otherwise, you
631 /// might end up persisting an attacker controlled file.
632 ///
633 /// # Errors
634 ///
635 /// If the file cannot be moved to the new location, `Err` is returned.
636 ///
637 /// # Examples
638 ///
639 /// ```no_run
640 /// # use std::io::{self, Write};
641 /// # extern crate tempfile;
642 /// use tempfile::NamedTempFile;
643 ///
644 /// # fn main() {
645 /// # if let Err(_) = run() {
646 /// # ::std::process::exit(1);
647 /// # }
648 /// # }
649 /// # fn run() -> Result<(), io::Error> {
650 /// let file = NamedTempFile::new()?;
651 ///
652 /// let mut persisted_file = file.persist("./saved_file.txt")?;
653 /// writeln!(persisted_file, "Brian was here. Briefly.")?;
654 /// # Ok(())
655 /// # }
656 /// ```
657 ///
658 /// [`PersistError`]: struct.PersistError.html
659 pub fn persist<P: AsRef<Path>>(self, new_path: P) -> Result<File, PersistError> {
660 let NamedTempFile { path, file } = self;
661 match path.persist(new_path) {
662 Ok(_) => Ok(file),
663 Err(err) => {
664 let PathPersistError { error, path } = err;
665 Err(PersistError {
666 file: NamedTempFile { path, file },
667 error,
668 })
669 }
670 }
671 }
672
673 /// Persist the temporary file at the target path iff no file exists there.
674 ///
675 /// If a file exists at the target path, fail. If this method fails, it will
676 /// return `self` in the resulting PersistError.
677 ///
678 /// Note: Temporary files cannot be persisted across filesystems. Also Note:
679 /// This method is not atomic. It can leave the original link to the
680 /// temporary file behind.
681 ///
682 /// # Security
683 ///
684 /// Only use this method if you're positive that a
685 /// temporary file cleaner won't have deleted your file. Otherwise, you
686 /// might end up persisting an attacker controlled file.
687 ///
688 /// # Errors
689 ///
690 /// If the file cannot be moved to the new location or a file already exists there,
691 /// `Err` is returned.
692 ///
693 /// # Examples
694 ///
695 /// ```no_run
696 /// # use std::io::{self, Write};
697 /// # extern crate tempfile;
698 /// use tempfile::NamedTempFile;
699 ///
700 /// # fn main() {
701 /// # if let Err(_) = run() {
702 /// # ::std::process::exit(1);
703 /// # }
704 /// # }
705 /// # fn run() -> Result<(), io::Error> {
706 /// let file = NamedTempFile::new()?;
707 ///
708 /// let mut persisted_file = file.persist_noclobber("./saved_file.txt")?;
709 /// writeln!(persisted_file, "Brian was here. Briefly.")?;
710 /// # Ok(())
711 /// # }
712 /// ```
713 pub fn persist_noclobber<P: AsRef<Path>>(self, new_path: P) -> Result<File, PersistError> {
714 let NamedTempFile { path, file } = self;
715 match path.persist_noclobber(new_path) {
716 Ok(_) => Ok(file),
717 Err(err) => {
718 let PathPersistError { error, path } = err;
719 Err(PersistError {
720 file: NamedTempFile { path, file },
721 error,
722 })
723 }
724 }
725 }
726
727 /// Keep the temporary file from being deleted. This function will turn the
728 /// temporary file into a non-temporary file without moving it.
729 ///
730 ///
731 /// # Errors
732 ///
733 /// On some platforms (e.g., Windows), we need to mark the file as
734 /// non-temporary. This operation could fail.
735 ///
736 /// # Examples
737 ///
738 /// ```no_run
739 /// # use std::io::{self, Write};
740 /// # extern crate tempfile;
741 /// use tempfile::NamedTempFile;
742 ///
743 /// # fn main() {
744 /// # if let Err(_) = run() {
745 /// # ::std::process::exit(1);
746 /// # }
747 /// # }
748 /// # fn run() -> Result<(), io::Error> {
749 /// let mut file = NamedTempFile::new()?;
750 /// writeln!(file, "Brian was here. Briefly.")?;
751 ///
752 /// let (file, path) = file.keep()?;
753 /// # Ok(())
754 /// # }
755 /// ```
756 ///
757 /// [`PathPersistError`]: struct.PathPersistError.html
758 pub fn keep(self) -> Result<(File, PathBuf), PersistError> {
759 let (file, path) = (self.file, self.path);
760 match path.keep() {
761 Ok(path) => Ok((file, path)),
762 Err(PathPersistError { error, path }) => Err(PersistError {
763 file: NamedTempFile { path, file },
764 error,
765 }),
766 }
767 }
768
769 /// Reopen the temporary file.
770 ///
771 /// This function is useful when you need multiple independent handles to
772 /// the same file. It's perfectly fine to drop the original `NamedTempFile`
773 /// while holding on to `File`s returned by this function; the `File`s will
774 /// remain usable. However, they may not be nameable.
775 ///
776 /// # Errors
777 ///
778 /// If the file cannot be reopened, `Err` is returned.
779 ///
780 /// # Examples
781 ///
782 /// ```no_run
783 /// # use std::io;
784 /// # extern crate tempfile;
785 /// use tempfile::NamedTempFile;
786 ///
787 /// # fn main() {
788 /// # if let Err(_) = run() {
789 /// # ::std::process::exit(1);
790 /// # }
791 /// # }
792 /// # fn run() -> Result<(), io::Error> {
793 /// let file = NamedTempFile::new()?;
794 ///
795 /// let another_handle = file.reopen()?;
796 /// # Ok(())
797 /// # }
798 /// ```
799 pub fn reopen(&self) -> io::Result<File> {
800 imp::reopen(self.as_file(), NamedTempFile::path(self))
801 .with_err_path(|| NamedTempFile::path(self))
802 }
803
804 /// Get a reference to the underlying file.
805 pub fn as_file(&self) -> &File {
806 &self.file
807 }
808
809 /// Get a mutable reference to the underlying file.
810 pub fn as_file_mut(&mut self) -> &mut File {
811 &mut self.file
812 }
813
814 /// Convert the temporary file into a `std::fs::File`.
815 ///
816 /// The inner file will be deleted.
817 pub fn into_file(self) -> File {
818 self.file
819 }
820
821 /// Closes the file, leaving only the temporary file path.
822 ///
823 /// This is useful when another process must be able to open the temporary
824 /// file.
825 pub fn into_temp_path(self) -> TempPath {
826 self.path
827 }
828
829 /// Converts the named temporary file into its constituent parts.
830 ///
831 /// Note: When the path is dropped, the file is deleted but the file handle
832 /// is still usable.
833 pub fn into_parts(self) -> (File, TempPath) {
834 (self.file, self.path)
835 }
836 }
837
838 impl Read for NamedTempFile {
839 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
840 self.as_file_mut().read(buf).with_err_path(|| self.path())
841 }
842 }
843
844 impl<'a> Read for &'a NamedTempFile {
845 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
846 self.as_file().read(buf).with_err_path(|| self.path())
847 }
848 }
849
850 impl Write for NamedTempFile {
851 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
852 self.as_file_mut().write(buf).with_err_path(|| self.path())
853 }
854 #[inline]
855 fn flush(&mut self) -> io::Result<()> {
856 self.as_file_mut().flush().with_err_path(|| self.path())
857 }
858 }
859
860 impl<'a> Write for &'a NamedTempFile {
861 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
862 self.as_file().write(buf).with_err_path(|| self.path())
863 }
864 #[inline]
865 fn flush(&mut self) -> io::Result<()> {
866 self.as_file().flush().with_err_path(|| self.path())
867 }
868 }
869
870 impl Seek for NamedTempFile {
871 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
872 self.as_file_mut().seek(pos).with_err_path(|| self.path())
873 }
874 }
875
876 impl<'a> Seek for &'a NamedTempFile {
877 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
878 self.as_file().seek(pos).with_err_path(|| self.path())
879 }
880 }
881
882 #[cfg(unix)]
883 impl std::os::unix::io::AsRawFd for NamedTempFile {
884 #[inline]
885 fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
886 self.as_file().as_raw_fd()
887 }
888 }
889
890 #[cfg(windows)]
891 impl std::os::windows::io::AsRawHandle for NamedTempFile {
892 #[inline]
893 fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
894 self.as_file().as_raw_handle()
895 }
896 }
897
898 pub(crate) fn create_named(mut path: PathBuf) -> io::Result<NamedTempFile> {
899 // Make the path absolute. Otherwise, changing directories could cause us to
900 // delete the wrong file.
901 if !path.is_absolute() {
902 path = env::current_dir()?.join(path)
903 }
904 imp::create_named(&path)
905 .with_err_path(|| path.clone())
906 .map(|file| NamedTempFile {
907 path: TempPath { path },
908 file,
909 })
910 }