@@ -14,26 +14,32 @@ use std::io::{self, Read, Seek, Write};
14
14
///
15
15
/// # Name-able, but not necessarily named
16
16
///
17
- /// By default, the file does not necessarily have an name until the file is written
18
- /// persistently.
17
+ /// By default, the file does not necessarily have an name until the file is
18
+ /// written persistently.
19
19
///
20
20
/// On some operating systems like Linux, it is possible to create anonymous
21
- /// temporary files that can still be written to disk persistently via `O_TMPFILE`.
22
- /// The advantage of this is that if the process (or operating system) crashes
23
- /// while the file is being written, the temporary space will be automatically cleaned up.
24
- /// For this reason, there is no API to retrieve the name, for either case.
21
+ /// temporary files that can still be written to disk persistently via
22
+ /// `O_TMPFILE`. The advantage of this is that if the process (or operating
23
+ /// system) crashes while the file is being written, the temporary space will
24
+ /// be automatically cleaned up. For this reason, there is no API to retrieve
25
+ /// the name, for either case.
25
26
///
26
- /// To more closely match the semantics of [`tempfile::tempfile`], use [`crate::TempFile::new_anonymous`].
27
+ /// To more closely match the semantics of [`tempfile::tempfile`], use
28
+ /// [`crate::TempFile::new_anonymous`].
27
29
///
28
30
/// # File permissions
29
31
///
30
- /// Unlike the tempfile crate, the default [`TempFile::new`] will use the same permissions as [`File::create_new`] in
31
- /// the Rust standard library. Concretely on Unix systems for example this can (depending on `umask`) result in
32
- /// files that are readable by all users. The rationale for this is to make it more ergonomic and natural to use this API to
33
- /// atomically create new files and replace existing ones. Many cases that want "private" files will
34
- /// prefer [`TempFile::new_anonymous`] to have the file not be accessible at all outside the current process.
32
+ /// Unlike the tempfile crate, the default [`TempFile::new`] will use the same
33
+ /// permissions as [`File::create_new`] in the Rust standard library.
34
+ /// Concretely on Unix systems for example this can (depending on `umask`)
35
+ /// result in files that are readable by all users. The rationale for this is
36
+ /// to make it more ergonomic and natural to use this API to atomically create
37
+ /// new files and replace existing ones. Many cases that want "private" files
38
+ /// will prefer [`TempFile::new_anonymous`] to have the file not be accessible
39
+ /// at all outside the current process.
35
40
///
36
- /// To fully control the permissions of the resulting file, you can use [`File::set_permissions`].
41
+ /// To fully control the permissions of the resulting file, you can use
42
+ /// [`File::set_permissions`].
37
43
///
38
44
/// [`tempfile::tempfile`]: https://docs.rs/tempfile/latest/tempfile/fn.tempfile.html
39
45
/// [`tempfile::NamedTempFile`]: https://docs.rs/tempfile/latest/tempfile/struct.NamedTempFile.html
@@ -57,18 +63,19 @@ impl<'d> Debug for TempFile<'d> {
57
63
fn new_tempfile_linux ( d : & Dir , anonymous : bool ) -> io:: Result < Option < File > > {
58
64
use cap_std:: io_lifetimes:: OwnedFd ;
59
65
use rustix:: fs:: { Mode , OFlags } ;
60
- // openat's API uses WRONLY. There may be use cases for reading too, so let's support it.
66
+ // openat's API uses WRONLY. There may be use cases for reading too, so let's
67
+ // support it.
61
68
let mut oflags = OFlags :: CLOEXEC | OFlags :: TMPFILE | OFlags :: RDWR ;
62
69
if anonymous {
63
70
oflags |= OFlags :: EXCL ;
64
71
}
65
- // We default to 0o666, same as main rust when creating new files; this will be modified by
66
- // umask: https://github.com/rust-lang/rust/blob/44628f7273052d0bb8e8218518dacab210e1fe0d/library/std/src/sys/unix/fs.rs#L762
72
+ // We default to 0o666, same as main rust when creating new files; this will be
73
+ // modified by umask: < https://github.com/rust-lang/rust/blob/44628f7273052d0bb8e8218518dacab210e1fe0d/library/std/src/sys/unix/fs.rs#L762>
67
74
let mode = Mode :: from_raw_mode ( 0o666 ) ;
68
75
// Happy path - Linux with O_TMPFILE
69
76
match rustix:: fs:: openat ( d, "." , oflags, mode) {
70
77
Ok ( r) => return Ok ( Some ( File :: from ( OwnedFd :: from ( r) ) ) ) ,
71
- // See https://github.com/Stebalien/tempfile/blob/1a40687e06eb656044e3d2dffa1379f04b3ef3fd/src/file/imp/unix.rs#L81
78
+ // See < https://github.com/Stebalien/tempfile/blob/1a40687e06eb656044e3d2dffa1379f04b3ef3fd/src/file/imp/unix.rs#L81>
72
79
// TODO: With newer Rust versions, this could be simplied to only write `Err` once.
73
80
Err ( rustix:: io:: Errno :: OPNOTSUPP )
74
81
| Err ( rustix:: io:: Errno :: ISDIR )
@@ -94,8 +101,9 @@ fn generate_name_in(subdir: &Dir, f: &File) -> io::Result<String> {
94
101
. map ( |( _, name) | name)
95
102
}
96
103
97
- /// Create a new temporary file in the target directory, which may or may not have a (randomly generated) name at this point.
98
- /// If anonymous is specified, the file will be deleted
104
+ /// Create a new temporary file in the target directory, which may or may not
105
+ /// have a (randomly generated) name at this point. If anonymous is specified,
106
+ /// the file will be deleted
99
107
fn new_tempfile ( d : & Dir , anonymous : bool ) -> io:: Result < ( File , Option < String > ) > {
100
108
// On Linux, try O_TMPFILE
101
109
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
@@ -125,8 +133,8 @@ impl<'d> TempFile<'d> {
125
133
Ok ( Self { dir, fd, name } )
126
134
}
127
135
128
- /// Crate a new temporary file in the provided directory that will not have a
129
- /// name. This corresponds to [`tempfile::tempfile_in`].
136
+ /// Crate a new temporary file in the provided directory that will not have
137
+ /// a name. This corresponds to [`tempfile::tempfile_in`].
130
138
///
131
139
/// [`tempfile::tempfile_in`]: https://docs.rs/tempfile/latest/tempfile/fn.tempfile_in.html
132
140
pub fn new_anonymous ( dir : & ' d Dir ) -> io:: Result < File > {
@@ -144,17 +152,18 @@ impl<'d> TempFile<'d> {
144
152
}
145
153
146
154
fn impl_replace ( mut self , destname : & OsStr ) -> io:: Result < ( ) > {
147
- // At this point on Linux if O_TMPFILE is used, we need to give the file a temporary name in
148
- // order to link it into place. There are patches to add an `AT_LINKAT_REPLACE`
149
- // API. With that we could skip this and have file-leak-proof atomic file replacement:
150
- // https://marc.info/?l=linux-fsdevel&m=158028833007418&w=2
155
+ // At this point on Linux if O_TMPFILE is used, we need to give the file a
156
+ // temporary name in order to link it into place. There are patches to
157
+ // add an `AT_LINKAT_REPLACE` API. With that we could skip this and
158
+ // have file-leak-proof atomic file replacement: < https://marc.info/?l=linux-fsdevel&m=158028833007418&w=2>
151
159
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
152
160
let tempname = self
153
161
. name
154
162
. take ( )
155
163
. map ( Ok )
156
164
. unwrap_or_else ( || generate_name_in ( self . dir , & self . fd ) ) ?;
157
- // SAFETY: We only support anonymous files on Linux, so the file must have a name here.
165
+ // SAFETY: We only support anonymous files on Linux, so the file must have a
166
+ // name here.
158
167
#[ cfg( not( any( target_os = "android" , target_os = "linux" ) ) ) ]
159
168
let tempname = self . name . take ( ) . unwrap ( ) ;
160
169
// And try the rename into place.
0 commit comments