]>
Commit | Line | Data |
---|---|---|
54a0048b | 1 | //! Filesystem manipulation operations. |
85aaf69f SL |
2 | //! |
3 | //! This module contains basic methods to manipulate the contents of the local | |
4 | //! filesystem. All methods in this module represent cross-platform filesystem | |
5 | //! operations. Extra platform-specific functionality can be found in the | |
6 | //! extension traits of `std::os::$platform`. | |
7 | ||
c34b1796 | 8 | #![stable(feature = "rust1", since = "1.0.0")] |
f035d41b | 9 | #![deny(unsafe_op_in_unsafe_fn)] |
85aaf69f | 10 | |
1b1a35ee XL |
11 | #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))] |
12 | mod tests; | |
13 | ||
532ac7d7 | 14 | use crate::ffi::OsString; |
60c5eb7d XL |
15 | use crate::fmt; |
16 | use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; | |
532ac7d7 XL |
17 | use crate::path::{Path, PathBuf}; |
18 | use crate::sys::fs as fs_imp; | |
60c5eb7d | 19 | use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; |
532ac7d7 | 20 | use crate::time::SystemTime; |
85aaf69f SL |
21 | |
22 | /// A reference to an open file on the filesystem. | |
23 | /// | |
24 | /// An instance of a `File` can be read and/or written depending on what options | |
3b2f2976 | 25 | /// it was opened with. Files also implement [`Seek`] to alter the logical cursor |
85aaf69f SL |
26 | /// that the file contains internally. |
27 | /// | |
532ac7d7 XL |
28 | /// Files are automatically closed when they go out of scope. Errors detected |
29 | /// on closing are ignored by the implementation of `Drop`. Use the method | |
30 | /// [`sync_all`] if these errors must be manually handled. | |
3157f602 | 31 | /// |
c34b1796 | 32 | /// # Examples |
85aaf69f | 33 | /// |
3dfed10e | 34 | /// Creates a new file and write bytes to it (you can also use [`write()`]): |
32a655c1 | 35 | /// |
85aaf69f | 36 | /// ```no_run |
32a655c1 | 37 | /// use std::fs::File; |
85aaf69f | 38 | /// use std::io::prelude::*; |
32a655c1 | 39 | /// |
0531ce1d XL |
40 | /// fn main() -> std::io::Result<()> { |
41 | /// let mut file = File::create("foo.txt")?; | |
42 | /// file.write_all(b"Hello, world!")?; | |
43 | /// Ok(()) | |
44 | /// } | |
32a655c1 SL |
45 | /// ``` |
46 | /// | |
e74abb32 | 47 | /// Read the contents of a file into a [`String`] (you can also use [`read`]): |
32a655c1 SL |
48 | /// |
49 | /// ```no_run | |
85aaf69f | 50 | /// use std::fs::File; |
32a655c1 | 51 | /// use std::io::prelude::*; |
85aaf69f | 52 | /// |
0531ce1d XL |
53 | /// fn main() -> std::io::Result<()> { |
54 | /// let mut file = File::open("foo.txt")?; | |
55 | /// let mut contents = String::new(); | |
56 | /// file.read_to_string(&mut contents)?; | |
57 | /// assert_eq!(contents, "Hello, world!"); | |
58 | /// Ok(()) | |
59 | /// } | |
32a655c1 | 60 | /// ``` |
85aaf69f | 61 | /// |
32a655c1 SL |
62 | /// It can be more efficient to read the contents of a file with a buffered |
63 | /// [`Read`]er. This can be accomplished with [`BufReader<R>`]: | |
64 | /// | |
65 | /// ```no_run | |
66 | /// use std::fs::File; | |
67 | /// use std::io::BufReader; | |
68 | /// use std::io::prelude::*; | |
69 | /// | |
0531ce1d XL |
70 | /// fn main() -> std::io::Result<()> { |
71 | /// let file = File::open("foo.txt")?; | |
72 | /// let mut buf_reader = BufReader::new(file); | |
73 | /// let mut contents = String::new(); | |
74 | /// buf_reader.read_to_string(&mut contents)?; | |
75 | /// assert_eq!(contents, "Hello, world!"); | |
76 | /// Ok(()) | |
77 | /// } | |
85aaf69f | 78 | /// ``` |
32a655c1 | 79 | /// |
0531ce1d XL |
80 | /// Note that, although read and write methods require a `&mut File`, because |
81 | /// of the interfaces for [`Read`] and [`Write`], the holder of a `&File` can | |
82 | /// still modify the file, either through methods that take `&File` or by | |
83 | /// retrieving the underlying OS object and modifying the file that way. | |
84 | /// Additionally, many operating systems allow concurrent modification of files | |
85 | /// by different processes. Avoid assuming that holding a `&File` means that the | |
86 | /// file will not change. | |
87 | /// | |
3dfed10e XL |
88 | /// [`BufReader<R>`]: io::BufReader |
89 | /// [`sync_all`]: File::sync_all | |
c34b1796 | 90 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
91 | pub struct File { |
92 | inner: fs_imp::File, | |
85aaf69f SL |
93 | } |
94 | ||
95 | /// Metadata information about a file. | |
96 | /// | |
32a655c1 SL |
97 | /// This structure is returned from the [`metadata`] or |
98 | /// [`symlink_metadata`] function or method and represents known | |
99 | /// metadata about a file such as its permissions, size, modification | |
100 | /// times, etc. | |
c34b1796 | 101 | #[stable(feature = "rust1", since = "1.0.0")] |
b039eaaf | 102 | #[derive(Clone)] |
85aaf69f SL |
103 | pub struct Metadata(fs_imp::FileAttr); |
104 | ||
105 | /// Iterator over the entries in a directory. | |
106 | /// | |
5bcae85e | 107 | /// This iterator is returned from the [`read_dir`] function of this module and |
3b2f2976 | 108 | /// will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. Through a [`DirEntry`] |
85aaf69f SL |
109 | /// information like the entry's path and possibly other metadata can be |
110 | /// learned. | |
c34b1796 | 111 | /// |
e74abb32 XL |
112 | /// The order in which this iterator returns entries is platform and filesystem |
113 | /// dependent. | |
114 | /// | |
7453a54e | 115 | /// # Errors |
c34b1796 | 116 | /// |
3b2f2976 | 117 | /// This [`io::Result`] will be an [`Err`] if there's some sort of intermittent |
c34b1796 AL |
118 | /// IO error during iteration. |
119 | #[stable(feature = "rust1", since = "1.0.0")] | |
c30ab7b3 | 120 | #[derive(Debug)] |
85aaf69f SL |
121 | pub struct ReadDir(fs_imp::ReadDir); |
122 | ||
5bcae85e SL |
123 | /// Entries returned by the [`ReadDir`] iterator. |
124 | /// | |
85aaf69f SL |
125 | /// An instance of `DirEntry` represents an entry inside of a directory on the |
126 | /// filesystem. Each entry can be inspected via methods to learn about the full | |
127 | /// path or possibly other metadata through per-platform extension traits. | |
c34b1796 | 128 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
129 | pub struct DirEntry(fs_imp::DirEntry); |
130 | ||
85aaf69f SL |
131 | /// Options and flags which can be used to configure how a file is opened. |
132 | /// | |
5bcae85e SL |
133 | /// This builder exposes the ability to configure how a [`File`] is opened and |
134 | /// what operations are permitted on the open file. The [`File::open`] and | |
135 | /// [`File::create`] methods are aliases for commonly used options using this | |
85aaf69f | 136 | /// builder. |
9346a6ac | 137 | /// |
3dfed10e XL |
138 | /// Generally speaking, when using `OpenOptions`, you'll first call |
139 | /// [`OpenOptions::new`], then chain calls to methods to set each option, then | |
140 | /// call [`OpenOptions::open`], passing the path of the file you're trying to | |
141 | /// open. This will give you a [`io::Result`] with a [`File`] inside that you | |
142 | /// can further operate on. | |
9346a6ac AL |
143 | /// |
144 | /// # Examples | |
145 | /// | |
146 | /// Opening a file to read: | |
147 | /// | |
148 | /// ```no_run | |
149 | /// use std::fs::OpenOptions; | |
150 | /// | |
151 | /// let file = OpenOptions::new().read(true).open("foo.txt"); | |
152 | /// ``` | |
153 | /// | |
154 | /// Opening a file for both reading and writing, as well as creating it if it | |
155 | /// doesn't exist: | |
156 | /// | |
157 | /// ```no_run | |
158 | /// use std::fs::OpenOptions; | |
159 | /// | |
160 | /// let file = OpenOptions::new() | |
161 | /// .read(true) | |
162 | /// .write(true) | |
163 | /// .create(true) | |
164 | /// .open("foo.txt"); | |
165 | /// ``` | |
32a655c1 | 166 | #[derive(Clone, Debug)] |
c34b1796 | 167 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
168 | pub struct OpenOptions(fs_imp::OpenOptions); |
169 | ||
170 | /// Representation of the various permissions on a file. | |
171 | /// | |
3dfed10e XL |
172 | /// This module only currently provides one bit of information, |
173 | /// [`Permissions::readonly`], which is exposed on all currently supported | |
174 | /// platforms. Unix-specific functionality, such as mode bits, is available | |
175 | /// through the [`PermissionsExt`] trait. | |
5bcae85e | 176 | /// |
3dfed10e | 177 | /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt |
85aaf69f | 178 | #[derive(Clone, PartialEq, Eq, Debug)] |
c34b1796 | 179 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
180 | pub struct Permissions(fs_imp::FilePermissions); |
181 | ||
5bcae85e SL |
182 | /// A structure representing a type of file with accessors for each file type. |
183 | /// It is returned by [`Metadata::file_type`] method. | |
d9579d0f | 184 | #[stable(feature = "file_type", since = "1.1.0")] |
5bcae85e | 185 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
d9579d0f AL |
186 | pub struct FileType(fs_imp::FileType); |
187 | ||
188 | /// A builder used to create directories in various manners. | |
189 | /// | |
190 | /// This builder also supports platform-specific options. | |
92a42be0 | 191 | #[stable(feature = "dir_builder", since = "1.6.0")] |
32a655c1 | 192 | #[derive(Debug)] |
d9579d0f AL |
193 | pub struct DirBuilder { |
194 | inner: fs_imp::DirBuilder, | |
195 | recursive: bool, | |
196 | } | |
197 | ||
532ac7d7 | 198 | /// Indicates how large a buffer to pre-allocate before reading the entire file. |
2c00a5a8 XL |
199 | fn initial_buffer_size(file: &File) -> usize { |
200 | // Allocate one extra byte so the buffer doesn't need to grow before the | |
201 | // final `read` call at the end of the file. Don't worry about `usize` | |
202 | // overflow because reading will fail regardless in that case. | |
203 | file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0) | |
204 | } | |
205 | ||
ff7c6d11 XL |
206 | /// Read the entire contents of a file into a bytes vector. |
207 | /// | |
208 | /// This is a convenience function for using [`File::open`] and [`read_to_end`] | |
9fa01778 | 209 | /// with fewer imports and without an intermediate variable. It pre-allocates a |
83c7162d | 210 | /// buffer based on the file size when available, so it is generally faster than |
3dfed10e | 211 | /// reading into a vector created with [`Vec::new()`]. |
ff7c6d11 | 212 | /// |
3dfed10e | 213 | /// [`read_to_end`]: Read::read_to_end |
ff7c6d11 XL |
214 | /// |
215 | /// # Errors | |
216 | /// | |
217 | /// This function will return an error if `path` does not already exist. | |
218 | /// Other errors may also be returned according to [`OpenOptions::open`]. | |
219 | /// | |
ff7c6d11 | 220 | /// It will also return an error if it encounters while reading an error |
3dfed10e | 221 | /// of a kind other than [`io::ErrorKind::Interrupted`]. |
ff7c6d11 XL |
222 | /// |
223 | /// # Examples | |
224 | /// | |
225 | /// ```no_run | |
ff7c6d11 XL |
226 | /// use std::fs; |
227 | /// use std::net::SocketAddr; | |
228 | /// | |
a1dfa0c6 | 229 | /// fn main() -> Result<(), Box<dyn std::error::Error + 'static>> { |
0531ce1d XL |
230 | /// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; |
231 | /// Ok(()) | |
232 | /// } | |
ff7c6d11 | 233 | /// ``` |
0531ce1d | 234 | #[stable(feature = "fs_read_write_bytes", since = "1.26.0")] |
ff7c6d11 | 235 | pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> { |
9fa01778 XL |
236 | fn inner(path: &Path) -> io::Result<Vec<u8>> { |
237 | let mut file = File::open(path)?; | |
238 | let mut bytes = Vec::with_capacity(initial_buffer_size(&file)); | |
239 | file.read_to_end(&mut bytes)?; | |
240 | Ok(bytes) | |
241 | } | |
242 | inner(path.as_ref()) | |
ff7c6d11 XL |
243 | } |
244 | ||
245 | /// Read the entire contents of a file into a string. | |
246 | /// | |
247 | /// This is a convenience function for using [`File::open`] and [`read_to_string`] | |
9fa01778 | 248 | /// with fewer imports and without an intermediate variable. It pre-allocates a |
83c7162d | 249 | /// buffer based on the file size when available, so it is generally faster than |
3dfed10e | 250 | /// reading into a string created with [`String::new()`]. |
ff7c6d11 | 251 | /// |
3dfed10e | 252 | /// [`read_to_string`]: Read::read_to_string |
ff7c6d11 XL |
253 | /// |
254 | /// # Errors | |
255 | /// | |
256 | /// This function will return an error if `path` does not already exist. | |
257 | /// Other errors may also be returned according to [`OpenOptions::open`]. | |
258 | /// | |
ff7c6d11 | 259 | /// It will also return an error if it encounters while reading an error |
3dfed10e | 260 | /// of a kind other than [`io::ErrorKind::Interrupted`], |
ff7c6d11 XL |
261 | /// or if the contents of the file are not valid UTF-8. |
262 | /// | |
ff7c6d11 XL |
263 | /// # Examples |
264 | /// | |
265 | /// ```no_run | |
ff7c6d11 XL |
266 | /// use std::fs; |
267 | /// use std::net::SocketAddr; | |
268 | /// | |
a1dfa0c6 | 269 | /// fn main() -> Result<(), Box<dyn std::error::Error + 'static>> { |
0531ce1d XL |
270 | /// let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?; |
271 | /// Ok(()) | |
272 | /// } | |
ff7c6d11 | 273 | /// ``` |
0531ce1d XL |
274 | #[stable(feature = "fs_read_write", since = "1.26.0")] |
275 | pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> { | |
9fa01778 XL |
276 | fn inner(path: &Path) -> io::Result<String> { |
277 | let mut file = File::open(path)?; | |
278 | let mut string = String::with_capacity(initial_buffer_size(&file)); | |
279 | file.read_to_string(&mut string)?; | |
280 | Ok(string) | |
281 | } | |
282 | inner(path.as_ref()) | |
ff7c6d11 XL |
283 | } |
284 | ||
285 | /// Write a slice as the entire contents of a file. | |
286 | /// | |
287 | /// This function will create a file if it does not exist, | |
288 | /// and will entirely replace its contents if it does. | |
289 | /// | |
290 | /// This is a convenience function for using [`File::create`] and [`write_all`] | |
291 | /// with fewer imports. | |
292 | /// | |
3dfed10e | 293 | /// [`write_all`]: Write::write_all |
ff7c6d11 XL |
294 | /// |
295 | /// # Examples | |
296 | /// | |
297 | /// ```no_run | |
ff7c6d11 XL |
298 | /// use std::fs; |
299 | /// | |
0531ce1d XL |
300 | /// fn main() -> std::io::Result<()> { |
301 | /// fs::write("foo.txt", b"Lorem ipsum")?; | |
94b46f34 | 302 | /// fs::write("bar.txt", "dolor sit")?; |
0531ce1d XL |
303 | /// Ok(()) |
304 | /// } | |
ff7c6d11 | 305 | /// ``` |
0531ce1d | 306 | #[stable(feature = "fs_read_write_bytes", since = "1.26.0")] |
ff7c6d11 | 307 | pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { |
9fa01778 XL |
308 | fn inner(path: &Path, contents: &[u8]) -> io::Result<()> { |
309 | File::create(path)?.write_all(contents) | |
310 | } | |
311 | inner(path.as_ref(), contents.as_ref()) | |
ff7c6d11 XL |
312 | } |
313 | ||
85aaf69f SL |
314 | impl File { |
315 | /// Attempts to open a file in read-only mode. | |
316 | /// | |
5bcae85e | 317 | /// See the [`OpenOptions::open`] method for more details. |
85aaf69f SL |
318 | /// |
319 | /// # Errors | |
320 | /// | |
321 | /// This function will return an error if `path` does not already exist. | |
5bcae85e SL |
322 | /// Other errors may also be returned according to [`OpenOptions::open`]. |
323 | /// | |
c34b1796 AL |
324 | /// # Examples |
325 | /// | |
326 | /// ```no_run | |
327 | /// use std::fs::File; | |
328 | /// | |
0531ce1d | 329 | /// fn main() -> std::io::Result<()> { |
8faf50e0 XL |
330 | /// let mut f = File::open("foo.txt")?; |
331 | /// Ok(()) | |
332 | /// } | |
c34b1796 AL |
333 | /// ``` |
334 | #[stable(feature = "rust1", since = "1.0.0")] | |
335 | pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> { | |
e9174d1e | 336 | OpenOptions::new().read(true).open(path.as_ref()) |
85aaf69f SL |
337 | } |
338 | ||
9346a6ac | 339 | /// Opens a file in write-only mode. |
85aaf69f SL |
340 | /// |
341 | /// This function will create a file if it does not exist, | |
342 | /// and will truncate it if it does. | |
343 | /// | |
5bcae85e SL |
344 | /// See the [`OpenOptions::open`] function for more details. |
345 | /// | |
c34b1796 AL |
346 | /// # Examples |
347 | /// | |
348 | /// ```no_run | |
349 | /// use std::fs::File; | |
350 | /// | |
0531ce1d XL |
351 | /// fn main() -> std::io::Result<()> { |
352 | /// let mut f = File::create("foo.txt")?; | |
353 | /// Ok(()) | |
354 | /// } | |
c34b1796 AL |
355 | /// ``` |
356 | #[stable(feature = "rust1", since = "1.0.0")] | |
357 | pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> { | |
e9174d1e | 358 | OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref()) |
85aaf69f SL |
359 | } |
360 | ||
e74abb32 XL |
361 | /// Returns a new OpenOptions object. |
362 | /// | |
363 | /// This function returns a new OpenOptions object that you can use to | |
364 | /// open or create a file with specific options if `open()` or `create()` | |
365 | /// are not appropriate. | |
366 | /// | |
367 | /// It is equivalent to `OpenOptions::new()` but allows you to write more | |
368 | /// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")` | |
74b04a01 | 369 | /// you can write `File::with_options().read(true).open("foo.txt")`. This |
e74abb32 XL |
370 | /// also avoids the need to import `OpenOptions`. |
371 | /// | |
372 | /// See the [`OpenOptions::new`] function for more details. | |
373 | /// | |
e74abb32 XL |
374 | /// # Examples |
375 | /// | |
376 | /// ```no_run | |
377 | /// #![feature(with_options)] | |
378 | /// use std::fs::File; | |
379 | /// | |
380 | /// fn main() -> std::io::Result<()> { | |
381 | /// let mut f = File::with_options().read(true).open("foo.txt")?; | |
382 | /// Ok(()) | |
383 | /// } | |
384 | /// ``` | |
385 | #[unstable(feature = "with_options", issue = "65439")] | |
386 | pub fn with_options() -> OpenOptions { | |
387 | OpenOptions::new() | |
388 | } | |
389 | ||
9346a6ac | 390 | /// Attempts to sync all OS-internal metadata to disk. |
85aaf69f | 391 | /// |
532ac7d7 | 392 | /// This function will attempt to ensure that all in-memory data reaches the |
85aaf69f | 393 | /// filesystem before returning. |
c34b1796 | 394 | /// |
532ac7d7 XL |
395 | /// This can be used to handle errors that would otherwise only be caught |
396 | /// when the `File` is closed. Dropping a file will ignore errors in | |
397 | /// synchronizing this in-memory data. | |
398 | /// | |
c34b1796 AL |
399 | /// # Examples |
400 | /// | |
401 | /// ```no_run | |
402 | /// use std::fs::File; | |
403 | /// use std::io::prelude::*; | |
404 | /// | |
0531ce1d XL |
405 | /// fn main() -> std::io::Result<()> { |
406 | /// let mut f = File::create("foo.txt")?; | |
407 | /// f.write_all(b"Hello, world!")?; | |
c34b1796 | 408 | /// |
0531ce1d XL |
409 | /// f.sync_all()?; |
410 | /// Ok(()) | |
411 | /// } | |
c34b1796 AL |
412 | /// ``` |
413 | #[stable(feature = "rust1", since = "1.0.0")] | |
85aaf69f SL |
414 | pub fn sync_all(&self) -> io::Result<()> { |
415 | self.inner.fsync() | |
416 | } | |
417 | ||
5bcae85e | 418 | /// This function is similar to [`sync_all`], except that it may not |
85aaf69f SL |
419 | /// synchronize file metadata to the filesystem. |
420 | /// | |
421 | /// This is intended for use cases that must synchronize content, but don't | |
422 | /// need the metadata on disk. The goal of this method is to reduce disk | |
423 | /// operations. | |
424 | /// | |
425 | /// Note that some platforms may simply implement this in terms of | |
5bcae85e SL |
426 | /// [`sync_all`]. |
427 | /// | |
3dfed10e | 428 | /// [`sync_all`]: File::sync_all |
c34b1796 AL |
429 | /// |
430 | /// # Examples | |
431 | /// | |
432 | /// ```no_run | |
433 | /// use std::fs::File; | |
434 | /// use std::io::prelude::*; | |
435 | /// | |
0531ce1d XL |
436 | /// fn main() -> std::io::Result<()> { |
437 | /// let mut f = File::create("foo.txt")?; | |
438 | /// f.write_all(b"Hello, world!")?; | |
c34b1796 | 439 | /// |
0531ce1d XL |
440 | /// f.sync_data()?; |
441 | /// Ok(()) | |
442 | /// } | |
c34b1796 AL |
443 | /// ``` |
444 | #[stable(feature = "rust1", since = "1.0.0")] | |
85aaf69f SL |
445 | pub fn sync_data(&self) -> io::Result<()> { |
446 | self.inner.datasync() | |
447 | } | |
448 | ||
449 | /// Truncates or extends the underlying file, updating the size of | |
450 | /// this file to become `size`. | |
451 | /// | |
452 | /// If the `size` is less than the current file's size, then the file will | |
453 | /// be shrunk. If it is greater than the current file's size, then the file | |
454 | /// will be extended to `size` and have all of the intermediate data filled | |
455 | /// in with 0s. | |
c34b1796 | 456 | /// |
0531ce1d XL |
457 | /// The file's cursor isn't changed. In particular, if the cursor was at the |
458 | /// end and the file is shrunk using this operation, the cursor will now be | |
459 | /// past the end. | |
460 | /// | |
c1a9b12d SL |
461 | /// # Errors |
462 | /// | |
463 | /// This function will return an error if the file is not opened for writing. | |
416331ca XL |
464 | /// Also, std::io::ErrorKind::InvalidInput will be returned if the desired |
465 | /// length would cause an overflow due to the implementation specifics. | |
c1a9b12d | 466 | /// |
c34b1796 AL |
467 | /// # Examples |
468 | /// | |
469 | /// ```no_run | |
470 | /// use std::fs::File; | |
471 | /// | |
0531ce1d XL |
472 | /// fn main() -> std::io::Result<()> { |
473 | /// let mut f = File::create("foo.txt")?; | |
474 | /// f.set_len(10)?; | |
475 | /// Ok(()) | |
476 | /// } | |
c34b1796 | 477 | /// ``` |
0531ce1d XL |
478 | /// |
479 | /// Note that this method alters the content of the underlying file, even | |
480 | /// though it takes `&self` rather than `&mut self`. | |
c34b1796 | 481 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
482 | pub fn set_len(&self, size: u64) -> io::Result<()> { |
483 | self.inner.truncate(size) | |
484 | } | |
485 | ||
c34b1796 AL |
486 | /// Queries metadata about the underlying file. |
487 | /// | |
488 | /// # Examples | |
489 | /// | |
490 | /// ```no_run | |
491 | /// use std::fs::File; | |
492 | /// | |
0531ce1d XL |
493 | /// fn main() -> std::io::Result<()> { |
494 | /// let mut f = File::open("foo.txt")?; | |
495 | /// let metadata = f.metadata()?; | |
496 | /// Ok(()) | |
497 | /// } | |
c34b1796 AL |
498 | /// ``` |
499 | #[stable(feature = "rust1", since = "1.0.0")] | |
85aaf69f SL |
500 | pub fn metadata(&self) -> io::Result<Metadata> { |
501 | self.inner.file_attr().map(Metadata) | |
502 | } | |
7453a54e | 503 | |
9fa01778 | 504 | /// Creates a new `File` instance that shares the same underlying file handle |
2c00a5a8 XL |
505 | /// as the existing `File` instance. Reads, writes, and seeks will affect |
506 | /// both `File` instances simultaneously. | |
5bcae85e SL |
507 | /// |
508 | /// # Examples | |
509 | /// | |
9fa01778 | 510 | /// Creates two handles for a file named `foo.txt`: |
2c00a5a8 | 511 | /// |
5bcae85e SL |
512 | /// ```no_run |
513 | /// use std::fs::File; | |
514 | /// | |
0531ce1d XL |
515 | /// fn main() -> std::io::Result<()> { |
516 | /// let mut file = File::open("foo.txt")?; | |
517 | /// let file_copy = file.try_clone()?; | |
518 | /// Ok(()) | |
519 | /// } | |
2c00a5a8 XL |
520 | /// ``` |
521 | /// | |
522 | /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create | |
523 | /// two handles, seek one of them, and read the remaining bytes from the | |
524 | /// other handle: | |
525 | /// | |
526 | /// ```no_run | |
527 | /// use std::fs::File; | |
528 | /// use std::io::SeekFrom; | |
529 | /// use std::io::prelude::*; | |
530 | /// | |
0531ce1d XL |
531 | /// fn main() -> std::io::Result<()> { |
532 | /// let mut file = File::open("foo.txt")?; | |
533 | /// let mut file_copy = file.try_clone()?; | |
2c00a5a8 | 534 | /// |
0531ce1d | 535 | /// file.seek(SeekFrom::Start(3))?; |
2c00a5a8 | 536 | /// |
0531ce1d XL |
537 | /// let mut contents = vec![]; |
538 | /// file_copy.read_to_end(&mut contents)?; | |
539 | /// assert_eq!(contents, b"def\n"); | |
540 | /// Ok(()) | |
541 | /// } | |
5bcae85e | 542 | /// ``` |
54a0048b | 543 | #[stable(feature = "file_try_clone", since = "1.9.0")] |
7453a54e | 544 | pub fn try_clone(&self) -> io::Result<File> { |
60c5eb7d | 545 | Ok(File { inner: self.inner.duplicate()? }) |
7453a54e | 546 | } |
476ff2be SL |
547 | |
548 | /// Changes the permissions on the underlying file. | |
549 | /// | |
550 | /// # Platform-specific behavior | |
551 | /// | |
552 | /// This function currently corresponds to the `fchmod` function on Unix and | |
553 | /// the `SetFileInformationByHandle` function on Windows. Note that, this | |
554 | /// [may change in the future][changes]. | |
555 | /// | |
1b1a35ee | 556 | /// [changes]: io#platform-specific-behavior |
476ff2be SL |
557 | /// |
558 | /// # Errors | |
559 | /// | |
560 | /// This function will return an error if the user lacks permission change | |
561 | /// attributes on the underlying file. It may also return an error in other | |
562 | /// os-specific unspecified cases. | |
563 | /// | |
564 | /// # Examples | |
565 | /// | |
0531ce1d XL |
566 | /// ```no_run |
567 | /// fn main() -> std::io::Result<()> { | |
568 | /// use std::fs::File; | |
569 | /// | |
570 | /// let file = File::open("foo.txt")?; | |
571 | /// let mut perms = file.metadata()?.permissions(); | |
572 | /// perms.set_readonly(true); | |
573 | /// file.set_permissions(perms)?; | |
574 | /// Ok(()) | |
575 | /// } | |
476ff2be | 576 | /// ``` |
476ff2be | 577 | /// |
0531ce1d XL |
578 | /// Note that this method alters the permissions of the underlying file, |
579 | /// even though it takes `&self` rather than `&mut self`. | |
32a655c1 | 580 | #[stable(feature = "set_permissions_atomic", since = "1.16.0")] |
476ff2be SL |
581 | pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> { |
582 | self.inner.set_permissions(perm.0) | |
583 | } | |
85aaf69f SL |
584 | } |
585 | ||
586 | impl AsInner<fs_imp::File> for File { | |
60c5eb7d XL |
587 | fn as_inner(&self) -> &fs_imp::File { |
588 | &self.inner | |
589 | } | |
85aaf69f | 590 | } |
c34b1796 AL |
591 | impl FromInner<fs_imp::File> for File { |
592 | fn from_inner(f: fs_imp::File) -> File { | |
d9579d0f AL |
593 | File { inner: f } |
594 | } | |
595 | } | |
c1a9b12d SL |
596 | impl IntoInner<fs_imp::File> for File { |
597 | fn into_inner(self) -> fs_imp::File { | |
598 | self.inner | |
599 | } | |
600 | } | |
d9579d0f | 601 | |
92a42be0 | 602 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 603 | impl fmt::Debug for File { |
532ac7d7 | 604 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
d9579d0f | 605 | self.inner.fmt(f) |
c34b1796 AL |
606 | } |
607 | } | |
608 | ||
609 | #[stable(feature = "rust1", since = "1.0.0")] | |
85aaf69f SL |
610 | impl Read for File { |
611 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
612 | self.inner.read(buf) | |
613 | } | |
041b39d2 | 614 | |
48663c56 XL |
615 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
616 | self.inner.read_vectored(bufs) | |
617 | } | |
618 | ||
f9f354fc XL |
619 | #[inline] |
620 | fn is_read_vectored(&self) -> bool { | |
621 | self.inner.is_read_vectored() | |
622 | } | |
623 | ||
041b39d2 XL |
624 | #[inline] |
625 | unsafe fn initializer(&self) -> Initializer { | |
f035d41b XL |
626 | // SAFETY: Read is guaranteed to work on uninitialized memory |
627 | unsafe { Initializer::nop() } | |
c1a9b12d | 628 | } |
85aaf69f | 629 | } |
c34b1796 | 630 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
631 | impl Write for File { |
632 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
633 | self.inner.write(buf) | |
634 | } | |
48663c56 XL |
635 | |
636 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { | |
637 | self.inner.write_vectored(bufs) | |
638 | } | |
639 | ||
f9f354fc XL |
640 | #[inline] |
641 | fn is_write_vectored(&self) -> bool { | |
642 | self.inner.is_write_vectored() | |
643 | } | |
644 | ||
60c5eb7d XL |
645 | fn flush(&mut self) -> io::Result<()> { |
646 | self.inner.flush() | |
647 | } | |
85aaf69f | 648 | } |
c34b1796 | 649 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
650 | impl Seek for File { |
651 | fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { | |
652 | self.inner.seek(pos) | |
653 | } | |
654 | } | |
c34b1796 | 655 | #[stable(feature = "rust1", since = "1.0.0")] |
9fa01778 | 656 | impl Read for &File { |
85aaf69f SL |
657 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
658 | self.inner.read(buf) | |
659 | } | |
041b39d2 | 660 | |
48663c56 XL |
661 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
662 | self.inner.read_vectored(bufs) | |
663 | } | |
664 | ||
f9f354fc XL |
665 | #[inline] |
666 | fn is_read_vectored(&self) -> bool { | |
667 | self.inner.is_read_vectored() | |
668 | } | |
669 | ||
041b39d2 XL |
670 | #[inline] |
671 | unsafe fn initializer(&self) -> Initializer { | |
f035d41b XL |
672 | // SAFETY: Read is guaranteed to work on uninitialized memory |
673 | unsafe { Initializer::nop() } | |
54a0048b | 674 | } |
85aaf69f | 675 | } |
c34b1796 | 676 | #[stable(feature = "rust1", since = "1.0.0")] |
9fa01778 | 677 | impl Write for &File { |
85aaf69f SL |
678 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
679 | self.inner.write(buf) | |
680 | } | |
48663c56 XL |
681 | |
682 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { | |
683 | self.inner.write_vectored(bufs) | |
684 | } | |
685 | ||
f9f354fc XL |
686 | #[inline] |
687 | fn is_write_vectored(&self) -> bool { | |
688 | self.inner.is_write_vectored() | |
689 | } | |
690 | ||
60c5eb7d XL |
691 | fn flush(&mut self) -> io::Result<()> { |
692 | self.inner.flush() | |
693 | } | |
85aaf69f | 694 | } |
c34b1796 | 695 | #[stable(feature = "rust1", since = "1.0.0")] |
9fa01778 | 696 | impl Seek for &File { |
85aaf69f SL |
697 | fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { |
698 | self.inner.seek(pos) | |
699 | } | |
700 | } | |
701 | ||
702 | impl OpenOptions { | |
7453a54e | 703 | /// Creates a blank new set of options ready for configuration. |
85aaf69f SL |
704 | /// |
705 | /// All options are initially set to `false`. | |
9346a6ac AL |
706 | /// |
707 | /// # Examples | |
708 | /// | |
709 | /// ```no_run | |
710 | /// use std::fs::OpenOptions; | |
711 | /// | |
7453a54e SL |
712 | /// let mut options = OpenOptions::new(); |
713 | /// let file = options.read(true).open("foo.txt"); | |
9346a6ac | 714 | /// ``` |
c34b1796 | 715 | #[stable(feature = "rust1", since = "1.0.0")] |
ba9703b0 | 716 | pub fn new() -> Self { |
85aaf69f SL |
717 | OpenOptions(fs_imp::OpenOptions::new()) |
718 | } | |
719 | ||
9346a6ac | 720 | /// Sets the option for read access. |
85aaf69f SL |
721 | /// |
722 | /// This option, when true, will indicate that the file should be | |
723 | /// `read`-able if opened. | |
9346a6ac AL |
724 | /// |
725 | /// # Examples | |
726 | /// | |
727 | /// ```no_run | |
728 | /// use std::fs::OpenOptions; | |
729 | /// | |
730 | /// let file = OpenOptions::new().read(true).open("foo.txt"); | |
731 | /// ``` | |
c34b1796 | 732 | #[stable(feature = "rust1", since = "1.0.0")] |
ba9703b0 | 733 | pub fn read(&mut self, read: bool) -> &mut Self { |
60c5eb7d XL |
734 | self.0.read(read); |
735 | self | |
85aaf69f SL |
736 | } |
737 | ||
9346a6ac | 738 | /// Sets the option for write access. |
85aaf69f SL |
739 | /// |
740 | /// This option, when true, will indicate that the file should be | |
741 | /// `write`-able if opened. | |
9346a6ac | 742 | /// |
7453a54e SL |
743 | /// If the file already exists, any write calls on it will overwrite its |
744 | /// contents, without truncating it. | |
745 | /// | |
9346a6ac AL |
746 | /// # Examples |
747 | /// | |
748 | /// ```no_run | |
749 | /// use std::fs::OpenOptions; | |
750 | /// | |
751 | /// let file = OpenOptions::new().write(true).open("foo.txt"); | |
752 | /// ``` | |
c34b1796 | 753 | #[stable(feature = "rust1", since = "1.0.0")] |
ba9703b0 | 754 | pub fn write(&mut self, write: bool) -> &mut Self { |
60c5eb7d XL |
755 | self.0.write(write); |
756 | self | |
85aaf69f SL |
757 | } |
758 | ||
9346a6ac | 759 | /// Sets the option for the append mode. |
85aaf69f SL |
760 | /// |
761 | /// This option, when true, means that writes will append to a file instead | |
762 | /// of overwriting previous contents. | |
7453a54e SL |
763 | /// Note that setting `.write(true).append(true)` has the same effect as |
764 | /// setting only `.append(true)`. | |
765 | /// | |
766 | /// For most filesystems, the operating system guarantees that all writes are | |
767 | /// atomic: no writes get mangled because another process writes at the same | |
768 | /// time. | |
769 | /// | |
770 | /// One maybe obvious note when using append-mode: make sure that all data | |
771 | /// that belongs together is written to the file in one operation. This | |
ea8adc8c | 772 | /// can be done by concatenating strings before passing them to [`write()`], |
7453a54e | 773 | /// or using a buffered writer (with a buffer of adequate size), |
ea8adc8c | 774 | /// and calling [`flush()`] when the message is complete. |
7453a54e SL |
775 | /// |
776 | /// If a file is opened with both read and append access, beware that after | |
777 | /// opening, and after every write, the position for reading may be set at the | |
778 | /// end of the file. So, before writing, save the current position (using | |
0bf4aa26 | 779 | /// [`seek`]`(`[`SeekFrom`]`::`[`Current`]`(0))`), and restore it before the next read. |
ea8adc8c XL |
780 | /// |
781 | /// ## Note | |
782 | /// | |
3dfed10e XL |
783 | /// This function doesn't create the file if it doesn't exist. Use the |
784 | /// [`OpenOptions::create`] method to do so. | |
ea8adc8c | 785 | /// |
3dfed10e XL |
786 | /// [`write()`]: Write::write |
787 | /// [`flush()`]: Write::flush | |
788 | /// [`seek`]: Seek::seek | |
789 | /// [`Current`]: SeekFrom::Current | |
9346a6ac AL |
790 | /// |
791 | /// # Examples | |
792 | /// | |
793 | /// ```no_run | |
794 | /// use std::fs::OpenOptions; | |
795 | /// | |
7453a54e | 796 | /// let file = OpenOptions::new().append(true).open("foo.txt"); |
9346a6ac | 797 | /// ``` |
c34b1796 | 798 | #[stable(feature = "rust1", since = "1.0.0")] |
ba9703b0 | 799 | pub fn append(&mut self, append: bool) -> &mut Self { |
60c5eb7d XL |
800 | self.0.append(append); |
801 | self | |
85aaf69f SL |
802 | } |
803 | ||
9346a6ac | 804 | /// Sets the option for truncating a previous file. |
85aaf69f SL |
805 | /// |
806 | /// If a file is successfully opened with this option set it will truncate | |
807 | /// the file to 0 length if it already exists. | |
9346a6ac | 808 | /// |
7453a54e SL |
809 | /// The file must be opened with write access for truncate to work. |
810 | /// | |
9346a6ac AL |
811 | /// # Examples |
812 | /// | |
813 | /// ```no_run | |
814 | /// use std::fs::OpenOptions; | |
815 | /// | |
c1a9b12d | 816 | /// let file = OpenOptions::new().write(true).truncate(true).open("foo.txt"); |
9346a6ac | 817 | /// ``` |
c34b1796 | 818 | #[stable(feature = "rust1", since = "1.0.0")] |
ba9703b0 | 819 | pub fn truncate(&mut self, truncate: bool) -> &mut Self { |
60c5eb7d XL |
820 | self.0.truncate(truncate); |
821 | self | |
85aaf69f SL |
822 | } |
823 | ||
74b04a01 | 824 | /// Sets the option to create a new file, or open it if it already exists. |
9346a6ac | 825 | /// |
3dfed10e XL |
826 | /// In order for the file to be created, [`OpenOptions::write`] or |
827 | /// [`OpenOptions::append`] access must be used. | |
ea8adc8c | 828 | /// |
9346a6ac AL |
829 | /// # Examples |
830 | /// | |
831 | /// ```no_run | |
832 | /// use std::fs::OpenOptions; | |
833 | /// | |
7453a54e | 834 | /// let file = OpenOptions::new().write(true).create(true).open("foo.txt"); |
9346a6ac | 835 | /// ``` |
c34b1796 | 836 | #[stable(feature = "rust1", since = "1.0.0")] |
ba9703b0 | 837 | pub fn create(&mut self, create: bool) -> &mut Self { |
60c5eb7d XL |
838 | self.0.create(create); |
839 | self | |
85aaf69f SL |
840 | } |
841 | ||
74b04a01 | 842 | /// Sets the option to create a new file, failing if it already exists. |
7453a54e | 843 | /// |
74b04a01 XL |
844 | /// No file is allowed to exist at the target location, also no (dangling) symlink. In this |
845 | /// way, if the call succeeds, the file returned is guaranteed to be new. | |
7453a54e | 846 | /// |
3157f602 | 847 | /// This option is useful because it is atomic. Otherwise between checking |
7453a54e SL |
848 | /// whether a file exists and creating a new one, the file may have been |
849 | /// created by another process (a TOCTOU race condition / attack). | |
850 | /// | |
ea8adc8c | 851 | /// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are |
7453a54e SL |
852 | /// ignored. |
853 | /// | |
854 | /// The file must be opened with write or append access in order to create | |
855 | /// a new file. | |
856 | /// | |
3dfed10e XL |
857 | /// [`.create()`]: OpenOptions::create |
858 | /// [`.truncate()`]: OpenOptions::truncate | |
ea8adc8c | 859 | /// |
7453a54e SL |
860 | /// # Examples |
861 | /// | |
862 | /// ```no_run | |
7453a54e SL |
863 | /// use std::fs::OpenOptions; |
864 | /// | |
865 | /// let file = OpenOptions::new().write(true) | |
866 | /// .create_new(true) | |
867 | /// .open("foo.txt"); | |
868 | /// ``` | |
54a0048b | 869 | #[stable(feature = "expand_open_options2", since = "1.9.0")] |
ba9703b0 | 870 | pub fn create_new(&mut self, create_new: bool) -> &mut Self { |
60c5eb7d XL |
871 | self.0.create_new(create_new); |
872 | self | |
7453a54e SL |
873 | } |
874 | ||
9346a6ac | 875 | /// Opens a file at `path` with the options specified by `self`. |
85aaf69f SL |
876 | /// |
877 | /// # Errors | |
878 | /// | |
879 | /// This function will return an error under a number of different | |
041b39d2 | 880 | /// circumstances. Some of these error conditions are listed here, together |
3dfed10e XL |
881 | /// with their [`io::ErrorKind`]. The mapping to [`io::ErrorKind`]s is not |
882 | /// part of the compatibility contract of the function, especially the | |
883 | /// [`Other`] kind might change to more specific kinds in the future. | |
041b39d2 XL |
884 | /// |
885 | /// * [`NotFound`]: The specified file does not exist and neither `create` | |
886 | /// or `create_new` is set. | |
887 | /// * [`NotFound`]: One of the directory components of the file path does | |
888 | /// not exist. | |
889 | /// * [`PermissionDenied`]: The user lacks permission to get the specified | |
890 | /// access rights for the file. | |
891 | /// * [`PermissionDenied`]: The user lacks permission to open one of the | |
892 | /// directory components of the specified path. | |
893 | /// * [`AlreadyExists`]: `create_new` was specified and the file already | |
894 | /// exists. | |
895 | /// * [`InvalidInput`]: Invalid combinations of open options (truncate | |
896 | /// without write access, no access mode set, etc.). | |
897 | /// * [`Other`]: One of the directory components of the specified file path | |
898 | /// was not, in fact, a directory. | |
899 | /// * [`Other`]: Filesystem-level errors: full disk, write permission | |
900 | /// requested on a read-only file system, exceeded disk quota, too many | |
901 | /// open files, too long filename, too many symbolic links in the | |
902 | /// specified path (Unix-like systems only), etc. | |
9346a6ac AL |
903 | /// |
904 | /// # Examples | |
905 | /// | |
906 | /// ```no_run | |
907 | /// use std::fs::OpenOptions; | |
908 | /// | |
60c5eb7d | 909 | /// let file = OpenOptions::new().read(true).open("foo.txt"); |
9346a6ac | 910 | /// ``` |
041b39d2 | 911 | /// |
3dfed10e XL |
912 | /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists |
913 | /// [`InvalidInput`]: io::ErrorKind::InvalidInput | |
914 | /// [`NotFound`]: io::ErrorKind::NotFound | |
915 | /// [`Other`]: io::ErrorKind::Other | |
916 | /// [`PermissionDenied`]: io::ErrorKind::PermissionDenied | |
c34b1796 AL |
917 | #[stable(feature = "rust1", since = "1.0.0")] |
918 | pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> { | |
e9174d1e SL |
919 | self._open(path.as_ref()) |
920 | } | |
921 | ||
922 | fn _open(&self, path: &Path) -> io::Result<File> { | |
48663c56 | 923 | fs_imp::File::open(path, &self.0).map(|inner| File { inner }) |
85aaf69f SL |
924 | } |
925 | } | |
c34b1796 | 926 | |
532ac7d7 | 927 | impl AsInner<fs_imp::OpenOptions> for OpenOptions { |
60c5eb7d XL |
928 | fn as_inner(&self) -> &fs_imp::OpenOptions { |
929 | &self.0 | |
930 | } | |
532ac7d7 XL |
931 | } |
932 | ||
85aaf69f | 933 | impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions { |
60c5eb7d XL |
934 | fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { |
935 | &mut self.0 | |
936 | } | |
85aaf69f SL |
937 | } |
938 | ||
939 | impl Metadata { | |
d9579d0f | 940 | /// Returns the file type for this metadata. |
5bcae85e SL |
941 | /// |
942 | /// # Examples | |
943 | /// | |
0531ce1d XL |
944 | /// ```no_run |
945 | /// fn main() -> std::io::Result<()> { | |
946 | /// use std::fs; | |
5bcae85e | 947 | /// |
0531ce1d | 948 | /// let metadata = fs::metadata("foo.txt")?; |
5bcae85e | 949 | /// |
0531ce1d XL |
950 | /// println!("{:?}", metadata.file_type()); |
951 | /// Ok(()) | |
952 | /// } | |
5bcae85e | 953 | /// ``` |
d9579d0f AL |
954 | #[stable(feature = "file_type", since = "1.1.0")] |
955 | pub fn file_type(&self) -> FileType { | |
956 | FileType(self.0.file_type()) | |
957 | } | |
958 | ||
9fa01778 | 959 | /// Returns `true` if this metadata is for a directory. The |
0531ce1d | 960 | /// result is mutually exclusive to the result of |
3dfed10e | 961 | /// [`Metadata::is_file`], and will be false for symlink metadata |
0531ce1d XL |
962 | /// obtained from [`symlink_metadata`]. |
963 | /// | |
9346a6ac AL |
964 | /// # Examples |
965 | /// | |
0531ce1d XL |
966 | /// ```no_run |
967 | /// fn main() -> std::io::Result<()> { | |
968 | /// use std::fs; | |
9346a6ac | 969 | /// |
0531ce1d | 970 | /// let metadata = fs::metadata("foo.txt")?; |
9346a6ac | 971 | /// |
0531ce1d XL |
972 | /// assert!(!metadata.is_dir()); |
973 | /// Ok(()) | |
974 | /// } | |
9346a6ac | 975 | /// ``` |
c34b1796 | 976 | #[stable(feature = "rust1", since = "1.0.0")] |
60c5eb7d XL |
977 | pub fn is_dir(&self) -> bool { |
978 | self.file_type().is_dir() | |
979 | } | |
85aaf69f | 980 | |
9fa01778 | 981 | /// Returns `true` if this metadata is for a regular file. The |
0531ce1d | 982 | /// result is mutually exclusive to the result of |
3dfed10e | 983 | /// [`Metadata::is_dir`], and will be false for symlink metadata |
0531ce1d XL |
984 | /// obtained from [`symlink_metadata`]. |
985 | /// | |
f035d41b XL |
986 | /// When the goal is simply to read from (or write to) the source, the most |
987 | /// reliable way to test the source can be read (or written to) is to open | |
988 | /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on | |
989 | /// a Unix-like system for example. See [`File::open`] or | |
990 | /// [`OpenOptions::open`] for more information. | |
991 | /// | |
9346a6ac AL |
992 | /// # Examples |
993 | /// | |
0531ce1d | 994 | /// ```no_run |
9346a6ac AL |
995 | /// use std::fs; |
996 | /// | |
0531ce1d XL |
997 | /// fn main() -> std::io::Result<()> { |
998 | /// let metadata = fs::metadata("foo.txt")?; | |
9346a6ac | 999 | /// |
0531ce1d XL |
1000 | /// assert!(metadata.is_file()); |
1001 | /// Ok(()) | |
1002 | /// } | |
9346a6ac | 1003 | /// ``` |
c34b1796 | 1004 | #[stable(feature = "rust1", since = "1.0.0")] |
60c5eb7d XL |
1005 | pub fn is_file(&self) -> bool { |
1006 | self.file_type().is_file() | |
1007 | } | |
85aaf69f SL |
1008 | |
1009 | /// Returns the size of the file, in bytes, this metadata is for. | |
9346a6ac AL |
1010 | /// |
1011 | /// # Examples | |
1012 | /// | |
0531ce1d | 1013 | /// ```no_run |
9346a6ac AL |
1014 | /// use std::fs; |
1015 | /// | |
0531ce1d XL |
1016 | /// fn main() -> std::io::Result<()> { |
1017 | /// let metadata = fs::metadata("foo.txt")?; | |
9346a6ac | 1018 | /// |
0531ce1d XL |
1019 | /// assert_eq!(0, metadata.len()); |
1020 | /// Ok(()) | |
1021 | /// } | |
9346a6ac | 1022 | /// ``` |
c34b1796 | 1023 | #[stable(feature = "rust1", since = "1.0.0")] |
60c5eb7d XL |
1024 | pub fn len(&self) -> u64 { |
1025 | self.0.size() | |
1026 | } | |
85aaf69f SL |
1027 | |
1028 | /// Returns the permissions of the file this metadata is for. | |
9346a6ac AL |
1029 | /// |
1030 | /// # Examples | |
1031 | /// | |
0531ce1d | 1032 | /// ```no_run |
9346a6ac AL |
1033 | /// use std::fs; |
1034 | /// | |
0531ce1d XL |
1035 | /// fn main() -> std::io::Result<()> { |
1036 | /// let metadata = fs::metadata("foo.txt")?; | |
9346a6ac | 1037 | /// |
0531ce1d XL |
1038 | /// assert!(!metadata.permissions().readonly()); |
1039 | /// Ok(()) | |
1040 | /// } | |
9346a6ac | 1041 | /// ``` |
c34b1796 | 1042 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
1043 | pub fn permissions(&self) -> Permissions { |
1044 | Permissions(self.0.perm()) | |
1045 | } | |
7453a54e SL |
1046 | |
1047 | /// Returns the last modification time listed in this metadata. | |
1048 | /// | |
1049 | /// The returned value corresponds to the `mtime` field of `stat` on Unix | |
1050 | /// platforms and the `ftLastWriteTime` field on Windows platforms. | |
1051 | /// | |
1052 | /// # Errors | |
1053 | /// | |
1054 | /// This field may not be available on all platforms, and will return an | |
1055 | /// `Err` on platforms where it is not available. | |
5bcae85e SL |
1056 | /// |
1057 | /// # Examples | |
1058 | /// | |
0531ce1d | 1059 | /// ```no_run |
5bcae85e SL |
1060 | /// use std::fs; |
1061 | /// | |
0531ce1d XL |
1062 | /// fn main() -> std::io::Result<()> { |
1063 | /// let metadata = fs::metadata("foo.txt")?; | |
5bcae85e | 1064 | /// |
0531ce1d XL |
1065 | /// if let Ok(time) = metadata.modified() { |
1066 | /// println!("{:?}", time); | |
1067 | /// } else { | |
1068 | /// println!("Not supported on this platform"); | |
1069 | /// } | |
1070 | /// Ok(()) | |
5bcae85e | 1071 | /// } |
5bcae85e | 1072 | /// ``` |
a7813a04 | 1073 | #[stable(feature = "fs_time", since = "1.10.0")] |
7453a54e SL |
1074 | pub fn modified(&self) -> io::Result<SystemTime> { |
1075 | self.0.modified().map(FromInner::from_inner) | |
1076 | } | |
1077 | ||
1078 | /// Returns the last access time of this metadata. | |
1079 | /// | |
1080 | /// The returned value corresponds to the `atime` field of `stat` on Unix | |
1081 | /// platforms and the `ftLastAccessTime` field on Windows platforms. | |
1082 | /// | |
1083 | /// Note that not all platforms will keep this field update in a file's | |
1084 | /// metadata, for example Windows has an option to disable updating this | |
1085 | /// time when files are accessed and Linux similarly has `noatime`. | |
1086 | /// | |
1087 | /// # Errors | |
1088 | /// | |
1089 | /// This field may not be available on all platforms, and will return an | |
1090 | /// `Err` on platforms where it is not available. | |
5bcae85e SL |
1091 | /// |
1092 | /// # Examples | |
1093 | /// | |
0531ce1d | 1094 | /// ```no_run |
5bcae85e SL |
1095 | /// use std::fs; |
1096 | /// | |
0531ce1d XL |
1097 | /// fn main() -> std::io::Result<()> { |
1098 | /// let metadata = fs::metadata("foo.txt")?; | |
5bcae85e | 1099 | /// |
0531ce1d XL |
1100 | /// if let Ok(time) = metadata.accessed() { |
1101 | /// println!("{:?}", time); | |
1102 | /// } else { | |
1103 | /// println!("Not supported on this platform"); | |
1104 | /// } | |
1105 | /// Ok(()) | |
5bcae85e | 1106 | /// } |
5bcae85e | 1107 | /// ``` |
a7813a04 | 1108 | #[stable(feature = "fs_time", since = "1.10.0")] |
7453a54e SL |
1109 | pub fn accessed(&self) -> io::Result<SystemTime> { |
1110 | self.0.accessed().map(FromInner::from_inner) | |
1111 | } | |
1112 | ||
2c00a5a8 | 1113 | /// Returns the creation time listed in this metadata. |
7453a54e | 1114 | /// |
e74abb32 XL |
1115 | /// The returned value corresponds to the `btime` field of `statx` on |
1116 | /// Linux kernel starting from to 4.11, the `birthtime` field of `stat` on other | |
1117 | /// Unix platforms, and the `ftCreationTime` field on Windows platforms. | |
7453a54e SL |
1118 | /// |
1119 | /// # Errors | |
1120 | /// | |
1121 | /// This field may not be available on all platforms, and will return an | |
e74abb32 | 1122 | /// `Err` on platforms or filesystems where it is not available. |
5bcae85e SL |
1123 | /// |
1124 | /// # Examples | |
1125 | /// | |
0531ce1d | 1126 | /// ```no_run |
5bcae85e SL |
1127 | /// use std::fs; |
1128 | /// | |
0531ce1d XL |
1129 | /// fn main() -> std::io::Result<()> { |
1130 | /// let metadata = fs::metadata("foo.txt")?; | |
5bcae85e | 1131 | /// |
0531ce1d XL |
1132 | /// if let Ok(time) = metadata.created() { |
1133 | /// println!("{:?}", time); | |
1134 | /// } else { | |
e74abb32 | 1135 | /// println!("Not supported on this platform or filesystem"); |
0531ce1d XL |
1136 | /// } |
1137 | /// Ok(()) | |
5bcae85e | 1138 | /// } |
5bcae85e | 1139 | /// ``` |
a7813a04 | 1140 | #[stable(feature = "fs_time", since = "1.10.0")] |
7453a54e SL |
1141 | pub fn created(&self) -> io::Result<SystemTime> { |
1142 | self.0.created().map(FromInner::from_inner) | |
1143 | } | |
d9579d0f | 1144 | } |
85aaf69f | 1145 | |
8bb4bdeb | 1146 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 | 1147 | impl fmt::Debug for Metadata { |
532ac7d7 | 1148 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
32a655c1 SL |
1149 | f.debug_struct("Metadata") |
1150 | .field("file_type", &self.file_type()) | |
1151 | .field("is_dir", &self.is_dir()) | |
1152 | .field("is_file", &self.is_file()) | |
1153 | .field("permissions", &self.permissions()) | |
1154 | .field("modified", &self.modified()) | |
1155 | .field("accessed", &self.accessed()) | |
1156 | .field("created", &self.created()) | |
1157 | .finish() | |
1158 | } | |
1159 | } | |
1160 | ||
d9579d0f | 1161 | impl AsInner<fs_imp::FileAttr> for Metadata { |
60c5eb7d XL |
1162 | fn as_inner(&self) -> &fs_imp::FileAttr { |
1163 | &self.0 | |
1164 | } | |
85aaf69f SL |
1165 | } |
1166 | ||
532ac7d7 | 1167 | impl FromInner<fs_imp::FileAttr> for Metadata { |
60c5eb7d XL |
1168 | fn from_inner(attr: fs_imp::FileAttr) -> Metadata { |
1169 | Metadata(attr) | |
1170 | } | |
532ac7d7 XL |
1171 | } |
1172 | ||
85aaf69f | 1173 | impl Permissions { |
9fa01778 | 1174 | /// Returns `true` if these permissions describe a readonly (unwritable) file. |
9346a6ac AL |
1175 | /// |
1176 | /// # Examples | |
1177 | /// | |
0531ce1d | 1178 | /// ```no_run |
9346a6ac AL |
1179 | /// use std::fs::File; |
1180 | /// | |
0531ce1d XL |
1181 | /// fn main() -> std::io::Result<()> { |
1182 | /// let mut f = File::create("foo.txt")?; | |
1183 | /// let metadata = f.metadata()?; | |
9346a6ac | 1184 | /// |
0531ce1d XL |
1185 | /// assert_eq!(false, metadata.permissions().readonly()); |
1186 | /// Ok(()) | |
1187 | /// } | |
9346a6ac | 1188 | /// ``` |
c34b1796 | 1189 | #[stable(feature = "rust1", since = "1.0.0")] |
60c5eb7d XL |
1190 | pub fn readonly(&self) -> bool { |
1191 | self.0.readonly() | |
1192 | } | |
85aaf69f | 1193 | |
3b2f2976 XL |
1194 | /// Modifies the readonly flag for this set of permissions. If the |
1195 | /// `readonly` argument is `true`, using the resulting `Permission` will | |
1196 | /// update file permissions to forbid writing. Conversely, if it's `false`, | |
1197 | /// using the resulting `Permission` will update file permissions to allow | |
1198 | /// writing. | |
85aaf69f SL |
1199 | /// |
1200 | /// This operation does **not** modify the filesystem. To modify the | |
3dfed10e | 1201 | /// filesystem use the [`set_permissions`] function. |
9346a6ac AL |
1202 | /// |
1203 | /// # Examples | |
1204 | /// | |
0531ce1d | 1205 | /// ```no_run |
9346a6ac AL |
1206 | /// use std::fs::File; |
1207 | /// | |
0531ce1d XL |
1208 | /// fn main() -> std::io::Result<()> { |
1209 | /// let f = File::create("foo.txt")?; | |
1210 | /// let metadata = f.metadata()?; | |
1211 | /// let mut permissions = metadata.permissions(); | |
9346a6ac | 1212 | /// |
0531ce1d | 1213 | /// permissions.set_readonly(true); |
9346a6ac | 1214 | /// |
0531ce1d XL |
1215 | /// // filesystem doesn't change |
1216 | /// assert_eq!(false, metadata.permissions().readonly()); | |
9346a6ac | 1217 | /// |
0531ce1d XL |
1218 | /// // just this particular `permissions`. |
1219 | /// assert_eq!(true, permissions.readonly()); | |
1220 | /// Ok(()) | |
1221 | /// } | |
9346a6ac | 1222 | /// ``` |
c34b1796 | 1223 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
1224 | pub fn set_readonly(&mut self, readonly: bool) { |
1225 | self.0.set_readonly(readonly) | |
1226 | } | |
1227 | } | |
1228 | ||
d9579d0f | 1229 | impl FileType { |
9fa01778 | 1230 | /// Tests whether this file type represents a directory. The |
0531ce1d XL |
1231 | /// result is mutually exclusive to the results of |
1232 | /// [`is_file`] and [`is_symlink`]; only zero or one of these | |
1233 | /// tests may pass. | |
1234 | /// | |
3dfed10e XL |
1235 | /// [`is_file`]: FileType::is_file |
1236 | /// [`is_symlink`]: FileType::is_symlink | |
5bcae85e SL |
1237 | /// |
1238 | /// # Examples | |
1239 | /// | |
0531ce1d XL |
1240 | /// ```no_run |
1241 | /// fn main() -> std::io::Result<()> { | |
1242 | /// use std::fs; | |
5bcae85e | 1243 | /// |
0531ce1d XL |
1244 | /// let metadata = fs::metadata("foo.txt")?; |
1245 | /// let file_type = metadata.file_type(); | |
5bcae85e | 1246 | /// |
0531ce1d XL |
1247 | /// assert_eq!(file_type.is_dir(), false); |
1248 | /// Ok(()) | |
1249 | /// } | |
5bcae85e | 1250 | /// ``` |
d9579d0f | 1251 | #[stable(feature = "file_type", since = "1.1.0")] |
60c5eb7d XL |
1252 | pub fn is_dir(&self) -> bool { |
1253 | self.0.is_dir() | |
1254 | } | |
d9579d0f | 1255 | |
9fa01778 | 1256 | /// Tests whether this file type represents a regular file. |
0531ce1d XL |
1257 | /// The result is mutually exclusive to the results of |
1258 | /// [`is_dir`] and [`is_symlink`]; only zero or one of these | |
1259 | /// tests may pass. | |
1260 | /// | |
f035d41b XL |
1261 | /// When the goal is simply to read from (or write to) the source, the most |
1262 | /// reliable way to test the source can be read (or written to) is to open | |
1263 | /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on | |
1264 | /// a Unix-like system for example. See [`File::open`] or | |
1265 | /// [`OpenOptions::open`] for more information. | |
1266 | /// | |
3dfed10e XL |
1267 | /// [`is_dir`]: FileType::is_dir |
1268 | /// [`is_symlink`]: FileType::is_symlink | |
5bcae85e SL |
1269 | /// |
1270 | /// # Examples | |
1271 | /// | |
0531ce1d XL |
1272 | /// ```no_run |
1273 | /// fn main() -> std::io::Result<()> { | |
1274 | /// use std::fs; | |
5bcae85e | 1275 | /// |
0531ce1d XL |
1276 | /// let metadata = fs::metadata("foo.txt")?; |
1277 | /// let file_type = metadata.file_type(); | |
5bcae85e | 1278 | /// |
0531ce1d XL |
1279 | /// assert_eq!(file_type.is_file(), true); |
1280 | /// Ok(()) | |
1281 | /// } | |
5bcae85e | 1282 | /// ``` |
d9579d0f | 1283 | #[stable(feature = "file_type", since = "1.1.0")] |
60c5eb7d XL |
1284 | pub fn is_file(&self) -> bool { |
1285 | self.0.is_file() | |
1286 | } | |
d9579d0f | 1287 | |
9fa01778 | 1288 | /// Tests whether this file type represents a symbolic link. |
0531ce1d XL |
1289 | /// The result is mutually exclusive to the results of |
1290 | /// [`is_dir`] and [`is_file`]; only zero or one of these | |
1291 | /// tests may pass. | |
5bcae85e | 1292 | /// |
32a655c1 SL |
1293 | /// The underlying [`Metadata`] struct needs to be retrieved |
1294 | /// with the [`fs::symlink_metadata`] function and not the | |
1295 | /// [`fs::metadata`] function. The [`fs::metadata`] function | |
1296 | /// follows symbolic links, so [`is_symlink`] would always | |
9fa01778 | 1297 | /// return `false` for the target file. |
32a655c1 | 1298 | /// |
3dfed10e XL |
1299 | /// [`fs::metadata`]: metadata |
1300 | /// [`fs::symlink_metadata`]: symlink_metadata | |
1301 | /// [`is_dir`]: FileType::is_dir | |
1302 | /// [`is_file`]: FileType::is_file | |
1303 | /// [`is_symlink`]: FileType::is_symlink | |
32a655c1 | 1304 | /// |
5bcae85e SL |
1305 | /// # Examples |
1306 | /// | |
0531ce1d | 1307 | /// ```no_run |
5bcae85e SL |
1308 | /// use std::fs; |
1309 | /// | |
0531ce1d XL |
1310 | /// fn main() -> std::io::Result<()> { |
1311 | /// let metadata = fs::symlink_metadata("foo.txt")?; | |
1312 | /// let file_type = metadata.file_type(); | |
5bcae85e | 1313 | /// |
0531ce1d XL |
1314 | /// assert_eq!(file_type.is_symlink(), false); |
1315 | /// Ok(()) | |
1316 | /// } | |
5bcae85e | 1317 | /// ``` |
d9579d0f | 1318 | #[stable(feature = "file_type", since = "1.1.0")] |
60c5eb7d XL |
1319 | pub fn is_symlink(&self) -> bool { |
1320 | self.0.is_symlink() | |
1321 | } | |
d9579d0f AL |
1322 | } |
1323 | ||
c1a9b12d | 1324 | impl AsInner<fs_imp::FileType> for FileType { |
60c5eb7d XL |
1325 | fn as_inner(&self) -> &fs_imp::FileType { |
1326 | &self.0 | |
1327 | } | |
c1a9b12d SL |
1328 | } |
1329 | ||
85aaf69f SL |
1330 | impl FromInner<fs_imp::FilePermissions> for Permissions { |
1331 | fn from_inner(f: fs_imp::FilePermissions) -> Permissions { | |
1332 | Permissions(f) | |
1333 | } | |
1334 | } | |
1335 | ||
c34b1796 | 1336 | impl AsInner<fs_imp::FilePermissions> for Permissions { |
60c5eb7d XL |
1337 | fn as_inner(&self) -> &fs_imp::FilePermissions { |
1338 | &self.0 | |
1339 | } | |
c34b1796 AL |
1340 | } |
1341 | ||
1342 | #[stable(feature = "rust1", since = "1.0.0")] | |
85aaf69f SL |
1343 | impl Iterator for ReadDir { |
1344 | type Item = io::Result<DirEntry>; | |
1345 | ||
1346 | fn next(&mut self) -> Option<io::Result<DirEntry>> { | |
1347 | self.0.next().map(|entry| entry.map(DirEntry)) | |
1348 | } | |
1349 | } | |
1350 | ||
1351 | impl DirEntry { | |
1352 | /// Returns the full path to the file that this entry represents. | |
1353 | /// | |
5bcae85e SL |
1354 | /// The full path is created by joining the original path to `read_dir` |
1355 | /// with the filename of this entry. | |
9346a6ac AL |
1356 | /// |
1357 | /// # Examples | |
1358 | /// | |
0531ce1d | 1359 | /// ```no_run |
9346a6ac | 1360 | /// use std::fs; |
0531ce1d XL |
1361 | /// |
1362 | /// fn main() -> std::io::Result<()> { | |
1363 | /// for entry in fs::read_dir(".")? { | |
1364 | /// let dir = entry?; | |
1365 | /// println!("{:?}", dir.path()); | |
1366 | /// } | |
1367 | /// Ok(()) | |
9346a6ac | 1368 | /// } |
9346a6ac AL |
1369 | /// ``` |
1370 | /// | |
1371 | /// This prints output like: | |
1372 | /// | |
1373 | /// ```text | |
1374 | /// "./whatever.txt" | |
1375 | /// "./foo.html" | |
1376 | /// "./hello_world.rs" | |
1377 | /// ``` | |
1378 | /// | |
1379 | /// The exact text, of course, depends on what files you have in `.`. | |
c34b1796 | 1380 | #[stable(feature = "rust1", since = "1.0.0")] |
60c5eb7d XL |
1381 | pub fn path(&self) -> PathBuf { |
1382 | self.0.path() | |
1383 | } | |
d9579d0f | 1384 | |
9fa01778 | 1385 | /// Returns the metadata for the file that this entry points at. |
d9579d0f AL |
1386 | /// |
1387 | /// This function will not traverse symlinks if this entry points at a | |
f035d41b XL |
1388 | /// symlink. To traverse symlinks use [`fs::metadata`] or [`fs::File::metadata`]. |
1389 | /// | |
3dfed10e XL |
1390 | /// [`fs::metadata`]: metadata |
1391 | /// [`fs::File::metadata`]: File::metadata | |
d9579d0f | 1392 | /// |
9cc50fc6 | 1393 | /// # Platform-specific behavior |
d9579d0f AL |
1394 | /// |
1395 | /// On Windows this function is cheap to call (no extra system calls | |
1396 | /// needed), but on Unix platforms this function is the equivalent of | |
1397 | /// calling `symlink_metadata` on the path. | |
5bcae85e SL |
1398 | /// |
1399 | /// # Examples | |
1400 | /// | |
1401 | /// ``` | |
1402 | /// use std::fs; | |
1403 | /// | |
1404 | /// if let Ok(entries) = fs::read_dir(".") { | |
1405 | /// for entry in entries { | |
1406 | /// if let Ok(entry) = entry { | |
1407 | /// // Here, `entry` is a `DirEntry`. | |
1408 | /// if let Ok(metadata) = entry.metadata() { | |
1409 | /// // Now let's show our entry's permissions! | |
1410 | /// println!("{:?}: {:?}", entry.path(), metadata.permissions()); | |
1411 | /// } else { | |
1412 | /// println!("Couldn't get metadata for {:?}", entry.path()); | |
1413 | /// } | |
1414 | /// } | |
1415 | /// } | |
1416 | /// } | |
1417 | /// ``` | |
d9579d0f AL |
1418 | #[stable(feature = "dir_entry_ext", since = "1.1.0")] |
1419 | pub fn metadata(&self) -> io::Result<Metadata> { | |
1420 | self.0.metadata().map(Metadata) | |
1421 | } | |
1422 | ||
9fa01778 | 1423 | /// Returns the file type for the file that this entry points at. |
d9579d0f AL |
1424 | /// |
1425 | /// This function will not traverse symlinks if this entry points at a | |
1426 | /// symlink. | |
1427 | /// | |
9cc50fc6 | 1428 | /// # Platform-specific behavior |
d9579d0f AL |
1429 | /// |
1430 | /// On Windows and most Unix platforms this function is free (no extra | |
1431 | /// system calls needed), but some Unix platforms may require the equivalent | |
1432 | /// call to `symlink_metadata` to learn about the target file type. | |
5bcae85e SL |
1433 | /// |
1434 | /// # Examples | |
1435 | /// | |
1436 | /// ``` | |
1437 | /// use std::fs; | |
1438 | /// | |
1439 | /// if let Ok(entries) = fs::read_dir(".") { | |
1440 | /// for entry in entries { | |
1441 | /// if let Ok(entry) = entry { | |
1442 | /// // Here, `entry` is a `DirEntry`. | |
1443 | /// if let Ok(file_type) = entry.file_type() { | |
1444 | /// // Now let's show our entry's file type! | |
1445 | /// println!("{:?}: {:?}", entry.path(), file_type); | |
1446 | /// } else { | |
1447 | /// println!("Couldn't get file type for {:?}", entry.path()); | |
1448 | /// } | |
1449 | /// } | |
1450 | /// } | |
1451 | /// } | |
1452 | /// ``` | |
d9579d0f AL |
1453 | #[stable(feature = "dir_entry_ext", since = "1.1.0")] |
1454 | pub fn file_type(&self) -> io::Result<FileType> { | |
1455 | self.0.file_type().map(FileType) | |
1456 | } | |
1457 | ||
1458 | /// Returns the bare file name of this directory entry without any other | |
1459 | /// leading path component. | |
5bcae85e SL |
1460 | /// |
1461 | /// # Examples | |
1462 | /// | |
1463 | /// ``` | |
1464 | /// use std::fs; | |
1465 | /// | |
1466 | /// if let Ok(entries) = fs::read_dir(".") { | |
1467 | /// for entry in entries { | |
1468 | /// if let Ok(entry) = entry { | |
1469 | /// // Here, `entry` is a `DirEntry`. | |
1470 | /// println!("{:?}", entry.file_name()); | |
1471 | /// } | |
1472 | /// } | |
1473 | /// } | |
1474 | /// ``` | |
d9579d0f AL |
1475 | #[stable(feature = "dir_entry_ext", since = "1.1.0")] |
1476 | pub fn file_name(&self) -> OsString { | |
1477 | self.0.file_name() | |
1478 | } | |
1479 | } | |
1480 | ||
9e0c209e SL |
1481 | #[stable(feature = "dir_entry_debug", since = "1.13.0")] |
1482 | impl fmt::Debug for DirEntry { | |
532ac7d7 | 1483 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
60c5eb7d | 1484 | f.debug_tuple("DirEntry").field(&self.path()).finish() |
9e0c209e SL |
1485 | } |
1486 | } | |
1487 | ||
d9579d0f | 1488 | impl AsInner<fs_imp::DirEntry> for DirEntry { |
60c5eb7d XL |
1489 | fn as_inner(&self) -> &fs_imp::DirEntry { |
1490 | &self.0 | |
1491 | } | |
85aaf69f SL |
1492 | } |
1493 | ||
e9174d1e | 1494 | /// Removes a file from the filesystem. |
85aaf69f | 1495 | /// |
e9174d1e | 1496 | /// Note that there is no |
0731742a | 1497 | /// guarantee that the file is immediately deleted (e.g., depending on |
85aaf69f SL |
1498 | /// platform, other open file descriptors may prevent immediate removal). |
1499 | /// | |
9cc50fc6 SL |
1500 | /// # Platform-specific behavior |
1501 | /// | |
1502 | /// This function currently corresponds to the `unlink` function on Unix | |
1503 | /// and the `DeleteFile` function on Windows. | |
1504 | /// Note that, this [may change in the future][changes]. | |
cc61c64b | 1505 | /// |
1b1a35ee | 1506 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 | 1507 | /// |
85aaf69f SL |
1508 | /// # Errors |
1509 | /// | |
9cc50fc6 SL |
1510 | /// This function will return an error in the following situations, but is not |
1511 | /// limited to just these cases: | |
1512 | /// | |
1513 | /// * `path` points to a directory. | |
3dfed10e | 1514 | /// * The file doesn't exist. |
9cc50fc6 | 1515 | /// * The user lacks permissions to remove the file. |
9346a6ac AL |
1516 | /// |
1517 | /// # Examples | |
1518 | /// | |
0531ce1d | 1519 | /// ```no_run |
9346a6ac AL |
1520 | /// use std::fs; |
1521 | /// | |
0531ce1d XL |
1522 | /// fn main() -> std::io::Result<()> { |
1523 | /// fs::remove_file("a.txt")?; | |
1524 | /// Ok(()) | |
1525 | /// } | |
9346a6ac | 1526 | /// ``` |
c34b1796 AL |
1527 | #[stable(feature = "rust1", since = "1.0.0")] |
1528 | pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> { | |
1529 | fs_imp::unlink(path.as_ref()) | |
85aaf69f SL |
1530 | } |
1531 | ||
1532 | /// Given a path, query the file system to get information about a file, | |
1533 | /// directory, etc. | |
1534 | /// | |
d9579d0f | 1535 | /// This function will traverse symbolic links to query information about the |
85aaf69f SL |
1536 | /// destination file. |
1537 | /// | |
9cc50fc6 SL |
1538 | /// # Platform-specific behavior |
1539 | /// | |
1540 | /// This function currently corresponds to the `stat` function on Unix | |
1541 | /// and the `GetFileAttributesEx` function on Windows. | |
1542 | /// Note that, this [may change in the future][changes]. | |
cc61c64b | 1543 | /// |
1b1a35ee | 1544 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 SL |
1545 | /// |
1546 | /// # Errors | |
1547 | /// | |
1548 | /// This function will return an error in the following situations, but is not | |
1549 | /// limited to just these cases: | |
1550 | /// | |
1551 | /// * The user lacks permissions to perform `metadata` call on `path`. | |
1552 | /// * `path` does not exist. | |
1553 | /// | |
c34b1796 | 1554 | /// # Examples |
85aaf69f | 1555 | /// |
0531ce1d | 1556 | /// ```rust,no_run |
85aaf69f SL |
1557 | /// use std::fs; |
1558 | /// | |
0531ce1d XL |
1559 | /// fn main() -> std::io::Result<()> { |
1560 | /// let attr = fs::metadata("/some/file/path.txt")?; | |
1561 | /// // inspect attr ... | |
1562 | /// Ok(()) | |
1563 | /// } | |
85aaf69f | 1564 | /// ``` |
c34b1796 AL |
1565 | #[stable(feature = "rust1", since = "1.0.0")] |
1566 | pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { | |
1567 | fs_imp::stat(path.as_ref()).map(Metadata) | |
85aaf69f SL |
1568 | } |
1569 | ||
d9579d0f AL |
1570 | /// Query the metadata about a file without following symlinks. |
1571 | /// | |
9cc50fc6 SL |
1572 | /// # Platform-specific behavior |
1573 | /// | |
1574 | /// This function currently corresponds to the `lstat` function on Unix | |
1575 | /// and the `GetFileAttributesEx` function on Windows. | |
1576 | /// Note that, this [may change in the future][changes]. | |
cc61c64b | 1577 | /// |
1b1a35ee | 1578 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 SL |
1579 | /// |
1580 | /// # Errors | |
1581 | /// | |
1582 | /// This function will return an error in the following situations, but is not | |
1583 | /// limited to just these cases: | |
1584 | /// | |
1585 | /// * The user lacks permissions to perform `metadata` call on `path`. | |
1586 | /// * `path` does not exist. | |
1587 | /// | |
d9579d0f AL |
1588 | /// # Examples |
1589 | /// | |
0531ce1d | 1590 | /// ```rust,no_run |
d9579d0f AL |
1591 | /// use std::fs; |
1592 | /// | |
0531ce1d XL |
1593 | /// fn main() -> std::io::Result<()> { |
1594 | /// let attr = fs::symlink_metadata("/some/file/path.txt")?; | |
1595 | /// // inspect attr ... | |
1596 | /// Ok(()) | |
1597 | /// } | |
d9579d0f AL |
1598 | /// ``` |
1599 | #[stable(feature = "symlink_metadata", since = "1.1.0")] | |
1600 | pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { | |
1601 | fs_imp::lstat(path.as_ref()).map(Metadata) | |
1602 | } | |
1603 | ||
a7813a04 XL |
1604 | /// Rename a file or directory to a new name, replacing the original file if |
1605 | /// `to` already exists. | |
85aaf69f | 1606 | /// |
62682a34 SL |
1607 | /// This will not work if the new name is on a different mount point. |
1608 | /// | |
9cc50fc6 SL |
1609 | /// # Platform-specific behavior |
1610 | /// | |
1611 | /// This function currently corresponds to the `rename` function on Unix | |
1612 | /// and the `MoveFileEx` function with the `MOVEFILE_REPLACE_EXISTING` flag on Windows. | |
a7813a04 XL |
1613 | /// |
1614 | /// Because of this, the behavior when both `from` and `to` exist differs. On | |
1615 | /// Unix, if `from` is a directory, `to` must also be an (empty) directory. If | |
1616 | /// `from` is not a directory, `to` must also be not a directory. In contrast, | |
1617 | /// on Windows, `from` can be anything, but `to` must *not* be a directory. | |
1618 | /// | |
9cc50fc6 | 1619 | /// Note that, this [may change in the future][changes]. |
cc61c64b | 1620 | /// |
1b1a35ee | 1621 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 | 1622 | /// |
85aaf69f SL |
1623 | /// # Errors |
1624 | /// | |
9cc50fc6 SL |
1625 | /// This function will return an error in the following situations, but is not |
1626 | /// limited to just these cases: | |
1627 | /// | |
1628 | /// * `from` does not exist. | |
1629 | /// * The user lacks permissions to view contents. | |
1630 | /// * `from` and `to` are on separate filesystems. | |
9346a6ac AL |
1631 | /// |
1632 | /// # Examples | |
1633 | /// | |
0531ce1d | 1634 | /// ```no_run |
9346a6ac AL |
1635 | /// use std::fs; |
1636 | /// | |
0531ce1d XL |
1637 | /// fn main() -> std::io::Result<()> { |
1638 | /// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt | |
1639 | /// Ok(()) | |
1640 | /// } | |
9346a6ac | 1641 | /// ``` |
c34b1796 AL |
1642 | #[stable(feature = "rust1", since = "1.0.0")] |
1643 | pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> { | |
1644 | fs_imp::rename(from.as_ref(), to.as_ref()) | |
85aaf69f SL |
1645 | } |
1646 | ||
1647 | /// Copies the contents of one file to another. This function will also | |
1648 | /// copy the permission bits of the original file to the destination file. | |
1649 | /// | |
1650 | /// This function will **overwrite** the contents of `to`. | |
1651 | /// | |
1652 | /// Note that if `from` and `to` both point to the same file, then the file | |
1653 | /// will likely get truncated by this operation. | |
1654 | /// | |
ea8adc8c XL |
1655 | /// On success, the total number of bytes copied is returned and it is equal to |
1656 | /// the length of the `to` file as reported by `metadata`. | |
e9174d1e | 1657 | /// |
b7449926 XL |
1658 | /// If you’re wanting to copy the contents of one file to another and you’re |
1659 | /// working with [`File`]s, see the [`io::copy`] function. | |
1660 | /// | |
9cc50fc6 SL |
1661 | /// # Platform-specific behavior |
1662 | /// | |
1663 | /// This function currently corresponds to the `open` function in Unix | |
1664 | /// with `O_RDONLY` for `from` and `O_WRONLY`, `O_CREAT`, and `O_TRUNC` for `to`. | |
1665 | /// `O_CLOEXEC` is set for returned file descriptors. | |
ea8adc8c XL |
1666 | /// On Windows, this function currently corresponds to `CopyFileEx`. Alternate |
1667 | /// NTFS streams are copied but only the size of the main stream is returned by | |
48663c56 XL |
1668 | /// this function. On MacOS, this function corresponds to `fclonefileat` and |
1669 | /// `fcopyfile`. | |
9cc50fc6 | 1670 | /// Note that, this [may change in the future][changes]. |
cc61c64b | 1671 | /// |
1b1a35ee | 1672 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 | 1673 | /// |
85aaf69f SL |
1674 | /// # Errors |
1675 | /// | |
1676 | /// This function will return an error in the following situations, but is not | |
1677 | /// limited to just these cases: | |
1678 | /// | |
9cc50fc6 SL |
1679 | /// * The `from` path is not a file. |
1680 | /// * The `from` file does not exist. | |
85aaf69f | 1681 | /// * The current process does not have the permission rights to access |
9cc50fc6 | 1682 | /// `from` or write `to`. |
9346a6ac AL |
1683 | /// |
1684 | /// # Examples | |
1685 | /// | |
1686 | /// ```no_run | |
1687 | /// use std::fs; | |
1688 | /// | |
0531ce1d XL |
1689 | /// fn main() -> std::io::Result<()> { |
1690 | /// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt | |
1691 | /// Ok(()) | |
1692 | /// } | |
9346a6ac | 1693 | /// ``` |
c34b1796 AL |
1694 | #[stable(feature = "rust1", since = "1.0.0")] |
1695 | pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> { | |
c1a9b12d | 1696 | fs_imp::copy(from.as_ref(), to.as_ref()) |
85aaf69f SL |
1697 | } |
1698 | ||
1699 | /// Creates a new hard link on the filesystem. | |
1700 | /// | |
1701 | /// The `dst` path will be a link pointing to the `src` path. Note that systems | |
1702 | /// often require these two paths to both be located on the same filesystem. | |
9346a6ac | 1703 | /// |
29967ef6 XL |
1704 | /// If `src` names a symbolic link, it is platform-specific whether the symbolic |
1705 | /// link is followed. On platforms where it's possible to not follow it, it is | |
1706 | /// not followed, and the created hard link points to the symbolic link itself. | |
1707 | /// | |
9cc50fc6 SL |
1708 | /// # Platform-specific behavior |
1709 | /// | |
29967ef6 XL |
1710 | /// This function currently corresponds to the `linkat` function with no flags |
1711 | /// on Unix and the `CreateHardLink` function on Windows. | |
9cc50fc6 | 1712 | /// Note that, this [may change in the future][changes]. |
cc61c64b | 1713 | /// |
1b1a35ee | 1714 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 SL |
1715 | /// |
1716 | /// # Errors | |
1717 | /// | |
1718 | /// This function will return an error in the following situations, but is not | |
1719 | /// limited to just these cases: | |
1720 | /// | |
1721 | /// * The `src` path is not a file or doesn't exist. | |
1722 | /// | |
9346a6ac AL |
1723 | /// # Examples |
1724 | /// | |
0531ce1d | 1725 | /// ```no_run |
9346a6ac AL |
1726 | /// use std::fs; |
1727 | /// | |
0531ce1d XL |
1728 | /// fn main() -> std::io::Result<()> { |
1729 | /// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt | |
1730 | /// Ok(()) | |
1731 | /// } | |
9346a6ac | 1732 | /// ``` |
c34b1796 AL |
1733 | #[stable(feature = "rust1", since = "1.0.0")] |
1734 | pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> { | |
1735 | fs_imp::link(src.as_ref(), dst.as_ref()) | |
85aaf69f SL |
1736 | } |
1737 | ||
d9579d0f | 1738 | /// Creates a new symbolic link on the filesystem. |
85aaf69f | 1739 | /// |
d9579d0f AL |
1740 | /// The `dst` path will be a symbolic link pointing to the `src` path. |
1741 | /// On Windows, this will be a file symlink, not a directory symlink; | |
9fa01778 XL |
1742 | /// for this reason, the platform-specific [`std::os::unix::fs::symlink`] |
1743 | /// and [`std::os::windows::fs::symlink_file`] or [`symlink_dir`] should be | |
d9579d0f | 1744 | /// used instead to make the intent explicit. |
9346a6ac | 1745 | /// |
3dfed10e XL |
1746 | /// [`std::os::unix::fs::symlink`]: crate::os::unix::fs::symlink |
1747 | /// [`std::os::windows::fs::symlink_file`]: crate::os::windows::fs::symlink_file | |
1748 | /// [`symlink_dir`]: crate::os::windows::fs::symlink_dir | |
9fa01778 | 1749 | /// |
9346a6ac AL |
1750 | /// # Examples |
1751 | /// | |
0531ce1d | 1752 | /// ```no_run |
9346a6ac AL |
1753 | /// use std::fs; |
1754 | /// | |
0531ce1d XL |
1755 | /// fn main() -> std::io::Result<()> { |
1756 | /// fs::soft_link("a.txt", "b.txt")?; | |
1757 | /// Ok(()) | |
1758 | /// } | |
9346a6ac | 1759 | /// ``` |
9cc50fc6 | 1760 | #[stable(feature = "rust1", since = "1.0.0")] |
60c5eb7d XL |
1761 | #[rustc_deprecated( |
1762 | since = "1.1.0", | |
1763 | reason = "replaced with std::os::unix::fs::symlink and \ | |
1764 | std::os::windows::fs::{symlink_file, symlink_dir}" | |
1765 | )] | |
c34b1796 AL |
1766 | pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> { |
1767 | fs_imp::symlink(src.as_ref(), dst.as_ref()) | |
85aaf69f SL |
1768 | } |
1769 | ||
d9579d0f | 1770 | /// Reads a symbolic link, returning the file that the link points to. |
85aaf69f | 1771 | /// |
9cc50fc6 SL |
1772 | /// # Platform-specific behavior |
1773 | /// | |
1774 | /// This function currently corresponds to the `readlink` function on Unix | |
1775 | /// and the `CreateFile` function with `FILE_FLAG_OPEN_REPARSE_POINT` and | |
1776 | /// `FILE_FLAG_BACKUP_SEMANTICS` flags on Windows. | |
1777 | /// Note that, this [may change in the future][changes]. | |
cc61c64b | 1778 | /// |
1b1a35ee | 1779 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 | 1780 | /// |
85aaf69f SL |
1781 | /// # Errors |
1782 | /// | |
9cc50fc6 SL |
1783 | /// This function will return an error in the following situations, but is not |
1784 | /// limited to just these cases: | |
1785 | /// | |
1786 | /// * `path` is not a symbolic link. | |
1787 | /// * `path` does not exist. | |
85aaf69f | 1788 | /// |
c34b1796 | 1789 | /// # Examples |
85aaf69f | 1790 | /// |
0531ce1d | 1791 | /// ```no_run |
85aaf69f SL |
1792 | /// use std::fs; |
1793 | /// | |
0531ce1d XL |
1794 | /// fn main() -> std::io::Result<()> { |
1795 | /// let path = fs::read_link("a.txt")?; | |
1796 | /// Ok(()) | |
1797 | /// } | |
85aaf69f | 1798 | /// ``` |
9346a6ac AL |
1799 | #[stable(feature = "rust1", since = "1.0.0")] |
1800 | pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> { | |
1801 | fs_imp::readlink(path.as_ref()) | |
1802 | } | |
1803 | ||
94b46f34 XL |
1804 | /// Returns the canonical, absolute form of a path with all intermediate |
1805 | /// components normalized and symbolic links resolved. | |
b039eaaf | 1806 | /// |
9cc50fc6 SL |
1807 | /// # Platform-specific behavior |
1808 | /// | |
1809 | /// This function currently corresponds to the `realpath` function on Unix | |
1810 | /// and the `CreateFile` and `GetFinalPathNameByHandle` functions on Windows. | |
1811 | /// Note that, this [may change in the future][changes]. | |
cc61c64b | 1812 | /// |
94b46f34 XL |
1813 | /// On Windows, this converts the path to use [extended length path][path] |
1814 | /// syntax, which allows your program to use longer path names, but means you | |
1815 | /// can only join backslash-delimited paths to it, and it may be incompatible | |
1816 | /// with other applications (if passed to the application on the command-line, | |
1817 | /// or written to a file another application may read). | |
1818 | /// | |
1b1a35ee | 1819 | /// [changes]: io#platform-specific-behavior |
dfeec247 | 1820 | /// [path]: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file |
9cc50fc6 SL |
1821 | /// |
1822 | /// # Errors | |
1823 | /// | |
1824 | /// This function will return an error in the following situations, but is not | |
1825 | /// limited to just these cases: | |
1826 | /// | |
1827 | /// * `path` does not exist. | |
0731742a | 1828 | /// * A non-final component in path is not a directory. |
b039eaaf SL |
1829 | /// |
1830 | /// # Examples | |
1831 | /// | |
0531ce1d | 1832 | /// ```no_run |
b039eaaf SL |
1833 | /// use std::fs; |
1834 | /// | |
0531ce1d XL |
1835 | /// fn main() -> std::io::Result<()> { |
1836 | /// let path = fs::canonicalize("../a/../foo.txt")?; | |
1837 | /// Ok(()) | |
1838 | /// } | |
b039eaaf SL |
1839 | /// ``` |
1840 | #[stable(feature = "fs_canonicalize", since = "1.5.0")] | |
d9579d0f AL |
1841 | pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> { |
1842 | fs_imp::canonicalize(path.as_ref()) | |
1843 | } | |
1844 | ||
9346a6ac | 1845 | /// Creates a new, empty directory at the provided path |
85aaf69f | 1846 | /// |
9cc50fc6 SL |
1847 | /// # Platform-specific behavior |
1848 | /// | |
1849 | /// This function currently corresponds to the `mkdir` function on Unix | |
1850 | /// and the `CreateDirectory` function on Windows. | |
1851 | /// Note that, this [may change in the future][changes]. | |
cc61c64b | 1852 | /// |
1b1a35ee | 1853 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 | 1854 | /// |
a1dfa0c6 XL |
1855 | /// **NOTE**: If a parent of the given path doesn't exist, this function will |
1856 | /// return an error. To create a directory and all its missing parents at the | |
1857 | /// same time, use the [`create_dir_all`] function. | |
1858 | /// | |
85aaf69f SL |
1859 | /// # Errors |
1860 | /// | |
9cc50fc6 SL |
1861 | /// This function will return an error in the following situations, but is not |
1862 | /// limited to just these cases: | |
1863 | /// | |
1864 | /// * User lacks permissions to create directory at `path`. | |
a1dfa0c6 XL |
1865 | /// * A parent of the given path doesn't exist. (To create a directory and all |
1866 | /// its missing parents at the same time, use the [`create_dir_all`] | |
1867 | /// function.) | |
9cc50fc6 | 1868 | /// * `path` already exists. |
9346a6ac AL |
1869 | /// |
1870 | /// # Examples | |
1871 | /// | |
0531ce1d | 1872 | /// ```no_run |
9346a6ac AL |
1873 | /// use std::fs; |
1874 | /// | |
0531ce1d XL |
1875 | /// fn main() -> std::io::Result<()> { |
1876 | /// fs::create_dir("/some/dir")?; | |
1877 | /// Ok(()) | |
1878 | /// } | |
9346a6ac | 1879 | /// ``` |
c34b1796 AL |
1880 | #[stable(feature = "rust1", since = "1.0.0")] |
1881 | pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { | |
d9579d0f | 1882 | DirBuilder::new().create(path.as_ref()) |
85aaf69f SL |
1883 | } |
1884 | ||
1885 | /// Recursively create a directory and all of its parent components if they | |
1886 | /// are missing. | |
1887 | /// | |
9cc50fc6 SL |
1888 | /// # Platform-specific behavior |
1889 | /// | |
1890 | /// This function currently corresponds to the `mkdir` function on Unix | |
1891 | /// and the `CreateDirectory` function on Windows. | |
1892 | /// Note that, this [may change in the future][changes]. | |
cc61c64b | 1893 | /// |
1b1a35ee | 1894 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 | 1895 | /// |
85aaf69f SL |
1896 | /// # Errors |
1897 | /// | |
9cc50fc6 SL |
1898 | /// This function will return an error in the following situations, but is not |
1899 | /// limited to just these cases: | |
1900 | /// | |
1901 | /// * If any directory in the path specified by `path` | |
85aaf69f SL |
1902 | /// does not already exist and it could not be created otherwise. The specific |
1903 | /// error conditions for when a directory is being created (after it is | |
9fa01778 | 1904 | /// determined to not exist) are outlined by [`fs::create_dir`]. |
9346a6ac | 1905 | /// |
cc61c64b | 1906 | /// Notable exception is made for situations where any of the directories |
7cac9316 | 1907 | /// specified in the `path` could not be created as it was being created concurrently. |
ea8adc8c XL |
1908 | /// Such cases are considered to be successful. That is, calling `create_dir_all` |
1909 | /// concurrently from multiple threads or processes is guaranteed not to fail | |
1910 | /// due to a race condition with itself. | |
cc61c64b | 1911 | /// |
3dfed10e | 1912 | /// [`fs::create_dir`]: create_dir |
9fa01778 | 1913 | /// |
9346a6ac AL |
1914 | /// # Examples |
1915 | /// | |
0531ce1d | 1916 | /// ```no_run |
9346a6ac AL |
1917 | /// use std::fs; |
1918 | /// | |
0531ce1d XL |
1919 | /// fn main() -> std::io::Result<()> { |
1920 | /// fs::create_dir_all("/some/dir")?; | |
1921 | /// Ok(()) | |
1922 | /// } | |
9346a6ac | 1923 | /// ``` |
c34b1796 AL |
1924 | #[stable(feature = "rust1", since = "1.0.0")] |
1925 | pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> { | |
d9579d0f | 1926 | DirBuilder::new().recursive(true).create(path.as_ref()) |
85aaf69f SL |
1927 | } |
1928 | ||
3dfed10e | 1929 | /// Removes an empty directory. |
9346a6ac | 1930 | /// |
9cc50fc6 SL |
1931 | /// # Platform-specific behavior |
1932 | /// | |
1933 | /// This function currently corresponds to the `rmdir` function on Unix | |
1934 | /// and the `RemoveDirectory` function on Windows. | |
1935 | /// Note that, this [may change in the future][changes]. | |
cc61c64b | 1936 | /// |
1b1a35ee | 1937 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 | 1938 | /// |
9346a6ac AL |
1939 | /// # Errors |
1940 | /// | |
9cc50fc6 SL |
1941 | /// This function will return an error in the following situations, but is not |
1942 | /// limited to just these cases: | |
1943 | /// | |
3dfed10e XL |
1944 | /// * `path` doesn't exist. |
1945 | /// * `path` isn't a directory. | |
9cc50fc6 SL |
1946 | /// * The user lacks permissions to remove the directory at the provided `path`. |
1947 | /// * The directory isn't empty. | |
85aaf69f | 1948 | /// |
c34b1796 | 1949 | /// # Examples |
85aaf69f | 1950 | /// |
0531ce1d | 1951 | /// ```no_run |
85aaf69f SL |
1952 | /// use std::fs; |
1953 | /// | |
0531ce1d XL |
1954 | /// fn main() -> std::io::Result<()> { |
1955 | /// fs::remove_dir("/some/dir")?; | |
1956 | /// Ok(()) | |
1957 | /// } | |
85aaf69f | 1958 | /// ``` |
c34b1796 AL |
1959 | #[stable(feature = "rust1", since = "1.0.0")] |
1960 | pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { | |
1961 | fs_imp::rmdir(path.as_ref()) | |
85aaf69f SL |
1962 | } |
1963 | ||
1964 | /// Removes a directory at this path, after removing all its contents. Use | |
1965 | /// carefully! | |
1966 | /// | |
d9579d0f AL |
1967 | /// This function does **not** follow symbolic links and it will simply remove the |
1968 | /// symbolic link itself. | |
85aaf69f | 1969 | /// |
9cc50fc6 SL |
1970 | /// # Platform-specific behavior |
1971 | /// | |
1972 | /// This function currently corresponds to `opendir`, `lstat`, `rm` and `rmdir` functions on Unix | |
1973 | /// and the `FindFirstFile`, `GetFileAttributesEx`, `DeleteFile`, and `RemoveDirectory` functions | |
1974 | /// on Windows. | |
1975 | /// Note that, this [may change in the future][changes]. | |
cc61c64b | 1976 | /// |
1b1a35ee | 1977 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 | 1978 | /// |
85aaf69f SL |
1979 | /// # Errors |
1980 | /// | |
9fa01778 XL |
1981 | /// See [`fs::remove_file`] and [`fs::remove_dir`]. |
1982 | /// | |
3dfed10e XL |
1983 | /// [`fs::remove_file`]: remove_file |
1984 | /// [`fs::remove_dir`]: remove_dir | |
9346a6ac AL |
1985 | /// |
1986 | /// # Examples | |
1987 | /// | |
0531ce1d | 1988 | /// ```no_run |
9346a6ac AL |
1989 | /// use std::fs; |
1990 | /// | |
0531ce1d XL |
1991 | /// fn main() -> std::io::Result<()> { |
1992 | /// fs::remove_dir_all("/some/dir")?; | |
1993 | /// Ok(()) | |
1994 | /// } | |
9346a6ac | 1995 | /// ``` |
c34b1796 AL |
1996 | #[stable(feature = "rust1", since = "1.0.0")] |
1997 | pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> { | |
7453a54e | 1998 | fs_imp::remove_dir_all(path.as_ref()) |
85aaf69f SL |
1999 | } |
2000 | ||
2001 | /// Returns an iterator over the entries within a directory. | |
2002 | /// | |
9e0c209e SL |
2003 | /// The iterator will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. |
2004 | /// New errors may be encountered after an iterator is initially constructed. | |
2005 | /// | |
9cc50fc6 SL |
2006 | /// # Platform-specific behavior |
2007 | /// | |
2008 | /// This function currently corresponds to the `opendir` function on Unix | |
e1599b0c XL |
2009 | /// and the `FindFirstFile` function on Windows. Advancing the iterator |
2010 | /// currently corresponds to `readdir` on Unix and `FindNextFile` on Windows. | |
9cc50fc6 | 2011 | /// Note that, this [may change in the future][changes]. |
cc61c64b | 2012 | /// |
1b1a35ee | 2013 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 | 2014 | /// |
e74abb32 XL |
2015 | /// The order in which this iterator returns entries is platform and filesystem |
2016 | /// dependent. | |
2017 | /// | |
9cc50fc6 SL |
2018 | /// # Errors |
2019 | /// | |
2020 | /// This function will return an error in the following situations, but is not | |
2021 | /// limited to just these cases: | |
2022 | /// | |
2023 | /// * The provided `path` doesn't exist. | |
2024 | /// * The process lacks permissions to view the contents. | |
2025 | /// * The `path` points at a non-directory file. | |
2026 | /// | |
c34b1796 | 2027 | /// # Examples |
85aaf69f | 2028 | /// |
c34b1796 | 2029 | /// ``` |
85aaf69f | 2030 | /// use std::io; |
62682a34 | 2031 | /// use std::fs::{self, DirEntry}; |
85aaf69f SL |
2032 | /// use std::path::Path; |
2033 | /// | |
54a0048b | 2034 | /// // one possible implementation of walking a directory only visiting files |
dc9dc135 | 2035 | /// fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> io::Result<()> { |
3157f602 | 2036 | /// if dir.is_dir() { |
32a655c1 SL |
2037 | /// for entry in fs::read_dir(dir)? { |
2038 | /// let entry = entry?; | |
3157f602 XL |
2039 | /// let path = entry.path(); |
2040 | /// if path.is_dir() { | |
32a655c1 | 2041 | /// visit_dirs(&path, cb)?; |
85aaf69f | 2042 | /// } else { |
62682a34 | 2043 | /// cb(&entry); |
85aaf69f SL |
2044 | /// } |
2045 | /// } | |
2046 | /// } | |
2047 | /// Ok(()) | |
2048 | /// } | |
2049 | /// ``` | |
e74abb32 XL |
2050 | /// |
2051 | /// ```rust,no_run | |
2052 | /// use std::{fs, io}; | |
2053 | /// | |
2054 | /// fn main() -> io::Result<()> { | |
2055 | /// let mut entries = fs::read_dir(".")? | |
2056 | /// .map(|res| res.map(|e| e.path())) | |
2057 | /// .collect::<Result<Vec<_>, io::Error>>()?; | |
2058 | /// | |
2059 | /// // The order in which `read_dir` returns entries is not guaranteed. If reproducible | |
2060 | /// // ordering is required the entries should be explicitly sorted. | |
2061 | /// | |
2062 | /// entries.sort(); | |
2063 | /// | |
2064 | /// // The entries have now been sorted by their path. | |
2065 | /// | |
2066 | /// Ok(()) | |
2067 | /// } | |
2068 | /// ``` | |
c34b1796 AL |
2069 | #[stable(feature = "rust1", since = "1.0.0")] |
2070 | pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> { | |
2071 | fs_imp::readdir(path.as_ref()).map(ReadDir) | |
85aaf69f SL |
2072 | } |
2073 | ||
85aaf69f SL |
2074 | /// Changes the permissions found on a file or a directory. |
2075 | /// | |
9cc50fc6 SL |
2076 | /// # Platform-specific behavior |
2077 | /// | |
2078 | /// This function currently corresponds to the `chmod` function on Unix | |
2079 | /// and the `SetFileAttributes` function on Windows. | |
2080 | /// Note that, this [may change in the future][changes]. | |
cc61c64b | 2081 | /// |
1b1a35ee | 2082 | /// [changes]: io#platform-specific-behavior |
9cc50fc6 SL |
2083 | /// |
2084 | /// # Errors | |
2085 | /// | |
2086 | /// This function will return an error in the following situations, but is not | |
2087 | /// limited to just these cases: | |
2088 | /// | |
2089 | /// * `path` does not exist. | |
2090 | /// * The user lacks the permission to change attributes of the file. | |
2091 | /// | |
c34b1796 | 2092 | /// # Examples |
85aaf69f | 2093 | /// |
0531ce1d | 2094 | /// ```no_run |
85aaf69f SL |
2095 | /// use std::fs; |
2096 | /// | |
0531ce1d XL |
2097 | /// fn main() -> std::io::Result<()> { |
2098 | /// let mut perms = fs::metadata("foo.txt")?.permissions(); | |
2099 | /// perms.set_readonly(true); | |
2100 | /// fs::set_permissions("foo.txt", perms)?; | |
2101 | /// Ok(()) | |
2102 | /// } | |
85aaf69f | 2103 | /// ``` |
d9579d0f | 2104 | #[stable(feature = "set_permissions", since = "1.1.0")] |
60c5eb7d | 2105 | pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> { |
c34b1796 | 2106 | fs_imp::set_perm(path.as_ref(), perm.0) |
85aaf69f SL |
2107 | } |
2108 | ||
d9579d0f AL |
2109 | impl DirBuilder { |
2110 | /// Creates a new set of options with default mode/security settings for all | |
2111 | /// platforms and also non-recursive. | |
5bcae85e SL |
2112 | /// |
2113 | /// # Examples | |
2114 | /// | |
2115 | /// ``` | |
2116 | /// use std::fs::DirBuilder; | |
2117 | /// | |
2118 | /// let builder = DirBuilder::new(); | |
2119 | /// ``` | |
92a42be0 | 2120 | #[stable(feature = "dir_builder", since = "1.6.0")] |
d9579d0f | 2121 | pub fn new() -> DirBuilder { |
60c5eb7d | 2122 | DirBuilder { inner: fs_imp::DirBuilder::new(), recursive: false } |
d9579d0f AL |
2123 | } |
2124 | ||
cc61c64b XL |
2125 | /// Indicates that directories should be created recursively, creating all |
2126 | /// parent directories. Parents that do not exist are created with the same | |
2127 | /// security and permissions settings. | |
d9579d0f | 2128 | /// |
5bcae85e SL |
2129 | /// This option defaults to `false`. |
2130 | /// | |
2131 | /// # Examples | |
2132 | /// | |
2133 | /// ``` | |
2134 | /// use std::fs::DirBuilder; | |
2135 | /// | |
2136 | /// let mut builder = DirBuilder::new(); | |
2137 | /// builder.recursive(true); | |
2138 | /// ``` | |
92a42be0 | 2139 | #[stable(feature = "dir_builder", since = "1.6.0")] |
d9579d0f AL |
2140 | pub fn recursive(&mut self, recursive: bool) -> &mut Self { |
2141 | self.recursive = recursive; | |
2142 | self | |
2143 | } | |
2144 | ||
9fa01778 | 2145 | /// Creates the specified directory with the options configured in this |
d9579d0f | 2146 | /// builder. |
92a42be0 | 2147 | /// |
cc61c64b XL |
2148 | /// It is considered an error if the directory already exists unless |
2149 | /// recursive mode is enabled. | |
2150 | /// | |
92a42be0 SL |
2151 | /// # Examples |
2152 | /// | |
2153 | /// ```no_run | |
2154 | /// use std::fs::{self, DirBuilder}; | |
2155 | /// | |
2156 | /// let path = "/tmp/foo/bar/baz"; | |
2157 | /// DirBuilder::new() | |
2158 | /// .recursive(true) | |
2159 | /// .create(path).unwrap(); | |
2160 | /// | |
2161 | /// assert!(fs::metadata(path).unwrap().is_dir()); | |
2162 | /// ``` | |
2163 | #[stable(feature = "dir_builder", since = "1.6.0")] | |
d9579d0f | 2164 | pub fn create<P: AsRef<Path>>(&self, path: P) -> io::Result<()> { |
e9174d1e SL |
2165 | self._create(path.as_ref()) |
2166 | } | |
2167 | ||
2168 | fn _create(&self, path: &Path) -> io::Result<()> { | |
60c5eb7d | 2169 | if self.recursive { self.create_dir_all(path) } else { self.inner.mkdir(path) } |
d9579d0f AL |
2170 | } |
2171 | ||
2172 | fn create_dir_all(&self, path: &Path) -> io::Result<()> { | |
cc61c64b | 2173 | if path == Path::new("") { |
60c5eb7d | 2174 | return Ok(()); |
cc61c64b XL |
2175 | } |
2176 | ||
2177 | match self.inner.mkdir(path) { | |
2178 | Ok(()) => return Ok(()), | |
2179 | Err(ref e) if e.kind() == io::ErrorKind::NotFound => {} | |
2180 | Err(_) if path.is_dir() => return Ok(()), | |
2181 | Err(e) => return Err(e), | |
2182 | } | |
2183 | match path.parent() { | |
a1dfa0c6 | 2184 | Some(p) => self.create_dir_all(p)?, |
60c5eb7d XL |
2185 | None => { |
2186 | return Err(io::Error::new(io::ErrorKind::Other, "failed to create whole tree")); | |
2187 | } | |
cc61c64b XL |
2188 | } |
2189 | match self.inner.mkdir(path) { | |
2190 | Ok(()) => Ok(()), | |
2191 | Err(_) if path.is_dir() => Ok(()), | |
2192 | Err(e) => Err(e), | |
d9579d0f | 2193 | } |
d9579d0f AL |
2194 | } |
2195 | } | |
2196 | ||
2197 | impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder { | |
2198 | fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder { | |
2199 | &mut self.inner | |
2200 | } | |
2201 | } |