]> git.proxmox.com Git - rustc.git/blame - library/std/src/os/unix/fs.rs
New upstream version 1.56.0~beta.4+dfsg1
[rustc.git] / library / std / src / os / unix / fs.rs
CommitLineData
d9579d0f
AL
1//! Unix-specific extensions to primitives in the `std::fs` module.
2
3#![stable(feature = "rust1", since = "1.0.0")]
4
cdc7bbd5 5use super::platform::fs::MetadataExt as _;
60c5eb7d 6use crate::fs::{self, OpenOptions, Permissions};
532ac7d7
XL
7use crate::io;
8use crate::path::Path;
9use crate::sys;
60c5eb7d 10use crate::sys_common::{AsInner, AsInnerMut, FromInner};
1b1a35ee 11// Used for `File::read` on intra-doc links
136023e0
XL
12use crate::ffi::OsStr;
13use crate::sealed::Sealed;
1b1a35ee
XL
14#[allow(unused_imports)]
15use io::{Read, Write};
d9579d0f 16
3dfed10e 17/// Unix-specific extensions to [`fs::File`].
476ff2be 18#[stable(feature = "file_offset", since = "1.15.0")]
c30ab7b3
SL
19pub trait FileExt {
20 /// Reads a number of bytes starting from a given offset.
21 ///
22 /// Returns the number of bytes read.
23 ///
24 /// The offset is relative to the start of the file and thus independent
25 /// from the current cursor.
26 ///
27 /// The current file cursor is not affected by this function.
28 ///
abe05a73 29 /// Note that similar to [`File::read`], it is not an error to return with a
c30ab7b3 30 /// short read.
abe05a73 31 ///
1b1a35ee 32 /// [`File::read`]: fs::File::read
abe05a73
XL
33 ///
34 /// # Examples
35 ///
0531ce1d
XL
36 /// ```no_run
37 /// use std::io;
abe05a73 38 /// use std::fs::File;
0531ce1d 39 /// use std::os::unix::prelude::FileExt;
abe05a73 40 ///
0531ce1d
XL
41 /// fn main() -> io::Result<()> {
42 /// let mut buf = [0u8; 8];
43 /// let file = File::open("foo.txt")?;
abe05a73 44 ///
0531ce1d
XL
45 /// // We now read 8 bytes from the offset 10.
46 /// let num_bytes_read = file.read_at(&mut buf, 10)?;
47 /// println!("read {} bytes: {:?}", num_bytes_read, buf);
48 /// Ok(())
49 /// }
abe05a73 50 /// ```
476ff2be 51 #[stable(feature = "file_offset", since = "1.15.0")]
c30ab7b3
SL
52 fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
53
8faf50e0
XL
54 /// Reads the exact number of byte required to fill `buf` from the given offset.
55 ///
56 /// The offset is relative to the start of the file and thus independent
57 /// from the current cursor.
58 ///
59 /// The current file cursor is not affected by this function.
60 ///
3dfed10e 61 /// Similar to [`io::Read::read_exact`] but uses [`read_at`] instead of `read`.
8faf50e0 62 ///
3dfed10e 63 /// [`read_at`]: FileExt::read_at
8faf50e0
XL
64 ///
65 /// # Errors
66 ///
67 /// If this function encounters an error of the kind
3dfed10e 68 /// [`io::ErrorKind::Interrupted`] then the error is ignored and the operation
8faf50e0
XL
69 /// will continue.
70 ///
71 /// If this function encounters an "end of file" before completely filling
3dfed10e 72 /// the buffer, it returns an error of the kind [`io::ErrorKind::UnexpectedEof`].
8faf50e0
XL
73 /// The contents of `buf` are unspecified in this case.
74 ///
75 /// If any other read error is encountered then this function immediately
76 /// returns. The contents of `buf` are unspecified in this case.
77 ///
78 /// If this function returns an error, it is unspecified how many bytes it
79 /// has read, but it will never read more than would be necessary to
80 /// completely fill the buffer.
81 ///
8faf50e0
XL
82 /// # Examples
83 ///
84 /// ```no_run
8faf50e0
XL
85 /// use std::io;
86 /// use std::fs::File;
87 /// use std::os::unix::prelude::FileExt;
88 ///
89 /// fn main() -> io::Result<()> {
90 /// let mut buf = [0u8; 8];
91 /// let file = File::open("foo.txt")?;
92 ///
93 /// // We now read exactly 8 bytes from the offset 10.
94 /// file.read_exact_at(&mut buf, 10)?;
95 /// println!("read {} bytes: {:?}", buf.len(), buf);
96 /// Ok(())
97 /// }
98 /// ```
0731742a 99 #[stable(feature = "rw_exact_all_at", since = "1.33.0")]
8faf50e0
XL
100 fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
101 while !buf.is_empty() {
102 match self.read_at(buf, offset) {
103 Ok(0) => break,
104 Ok(n) => {
105 let tmp = buf;
106 buf = &mut tmp[n..];
107 offset += n as u64;
108 }
109 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
110 Err(e) => return Err(e),
111 }
112 }
113 if !buf.is_empty() {
cdc7bbd5 114 Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer"))
8faf50e0
XL
115 } else {
116 Ok(())
117 }
118 }
119
c30ab7b3
SL
120 /// Writes a number of bytes starting from a given offset.
121 ///
122 /// Returns the number of bytes written.
123 ///
124 /// The offset is relative to the start of the file and thus independent
125 /// from the current cursor.
126 ///
127 /// The current file cursor is not affected by this function.
128 ///
3b2f2976 129 /// When writing beyond the end of the file, the file is appropriately
c30ab7b3
SL
130 /// extended and the intermediate bytes are initialized with the value 0.
131 ///
abe05a73 132 /// Note that similar to [`File::write`], it is not an error to return a
c30ab7b3 133 /// short write.
abe05a73 134 ///
1b1a35ee 135 /// [`File::write`]: fs::File::write
abe05a73
XL
136 ///
137 /// # Examples
138 ///
0531ce1d 139 /// ```no_run
abe05a73 140 /// use std::fs::File;
0531ce1d
XL
141 /// use std::io;
142 /// use std::os::unix::prelude::FileExt;
abe05a73 143 ///
0531ce1d
XL
144 /// fn main() -> io::Result<()> {
145 /// let file = File::open("foo.txt")?;
abe05a73 146 ///
0531ce1d
XL
147 /// // We now write at the offset 10.
148 /// file.write_at(b"sushi", 10)?;
149 /// Ok(())
150 /// }
abe05a73 151 /// ```
476ff2be 152 #[stable(feature = "file_offset", since = "1.15.0")]
c30ab7b3 153 fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
8faf50e0
XL
154
155 /// Attempts to write an entire buffer starting from a given offset.
156 ///
157 /// The offset is relative to the start of the file and thus independent
158 /// from the current cursor.
159 ///
160 /// The current file cursor is not affected by this function.
161 ///
162 /// This method will continuously call [`write_at`] until there is no more data
3dfed10e 163 /// to be written or an error of non-[`io::ErrorKind::Interrupted`] kind is
8faf50e0
XL
164 /// returned. This method will not return until the entire buffer has been
165 /// successfully written or such an error occurs. The first error that is
3dfed10e 166 /// not of [`io::ErrorKind::Interrupted`] kind generated from this method will be
8faf50e0
XL
167 /// returned.
168 ///
169 /// # Errors
170 ///
171 /// This function will return the first error of
3dfed10e 172 /// non-[`io::ErrorKind::Interrupted`] kind that [`write_at`] returns.
8faf50e0 173 ///
3dfed10e 174 /// [`write_at`]: FileExt::write_at
8faf50e0
XL
175 ///
176 /// # Examples
177 ///
178 /// ```no_run
8faf50e0
XL
179 /// use std::fs::File;
180 /// use std::io;
181 /// use std::os::unix::prelude::FileExt;
182 ///
183 /// fn main() -> io::Result<()> {
184 /// let file = File::open("foo.txt")?;
185 ///
186 /// // We now write at the offset 10.
187 /// file.write_all_at(b"sushi", 10)?;
188 /// Ok(())
189 /// }
190 /// ```
0731742a 191 #[stable(feature = "rw_exact_all_at", since = "1.33.0")]
8faf50e0
XL
192 fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
193 while !buf.is_empty() {
194 match self.write_at(buf, offset) {
60c5eb7d 195 Ok(0) => {
cdc7bbd5 196 return Err(io::Error::new_const(
60c5eb7d 197 io::ErrorKind::WriteZero,
cdc7bbd5 198 &"failed to write whole buffer",
60c5eb7d
XL
199 ));
200 }
8faf50e0
XL
201 Ok(n) => {
202 buf = &buf[n..];
203 offset += n as u64
204 }
205 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
206 Err(e) => return Err(e),
207 }
208 }
209 Ok(())
210 }
c30ab7b3
SL
211}
212
476ff2be 213#[stable(feature = "file_offset", since = "1.15.0")]
c30ab7b3
SL
214impl FileExt for fs::File {
215 fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
216 self.as_inner().read_at(buf, offset)
217 }
218 fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
219 self.as_inner().write_at(buf, offset)
220 }
221}
222
83c7162d 223/// Unix-specific extensions to [`fs::Permissions`].
d9579d0f
AL
224#[stable(feature = "fs_ext", since = "1.1.0")]
225pub trait PermissionsExt {
ea8adc8c
XL
226 /// Returns the underlying raw `st_mode` bits that contain the standard
227 /// Unix permissions for this file.
5bcae85e
SL
228 ///
229 /// # Examples
230 ///
041b39d2 231 /// ```no_run
5bcae85e
SL
232 /// use std::fs::File;
233 /// use std::os::unix::fs::PermissionsExt;
234 ///
0531ce1d
XL
235 /// fn main() -> std::io::Result<()> {
236 /// let f = File::create("foo.txt")?;
237 /// let metadata = f.metadata()?;
238 /// let permissions = metadata.permissions();
5bcae85e 239 ///
dc9dc135 240 /// println!("permissions: {:o}", permissions.mode());
f035d41b
XL
241 /// Ok(())
242 /// }
5bcae85e 243 /// ```
d9579d0f 244 #[stable(feature = "fs_ext", since = "1.1.0")]
7453a54e 245 fn mode(&self) -> u32;
d9579d0f 246
7453a54e 247 /// Sets the underlying raw bits for this set of permissions.
5bcae85e
SL
248 ///
249 /// # Examples
250 ///
041b39d2 251 /// ```no_run
5bcae85e
SL
252 /// use std::fs::File;
253 /// use std::os::unix::fs::PermissionsExt;
254 ///
0531ce1d
XL
255 /// fn main() -> std::io::Result<()> {
256 /// let f = File::create("foo.txt")?;
257 /// let metadata = f.metadata()?;
258 /// let mut permissions = metadata.permissions();
5bcae85e 259 ///
0531ce1d
XL
260 /// permissions.set_mode(0o644); // Read/write for owner and read for others.
261 /// assert_eq!(permissions.mode(), 0o644);
f035d41b
XL
262 /// Ok(())
263 /// }
5bcae85e 264 /// ```
d9579d0f 265 #[stable(feature = "fs_ext", since = "1.1.0")]
7453a54e 266 fn set_mode(&mut self, mode: u32);
d9579d0f
AL
267
268 /// Creates a new instance of `Permissions` from the given set of Unix
269 /// permission bits.
5bcae85e
SL
270 ///
271 /// # Examples
272 ///
041b39d2 273 /// ```
5bcae85e
SL
274 /// use std::fs::Permissions;
275 /// use std::os::unix::fs::PermissionsExt;
276 ///
277 /// // Read/write for owner and read for others.
278 /// let permissions = Permissions::from_mode(0o644);
279 /// assert_eq!(permissions.mode(), 0o644);
280 /// ```
d9579d0f 281 #[stable(feature = "fs_ext", since = "1.1.0")]
7453a54e 282 fn from_mode(mode: u32) -> Self;
d9579d0f
AL
283}
284
285#[stable(feature = "fs_ext", since = "1.1.0")]
286impl PermissionsExt for Permissions {
7453a54e
SL
287 fn mode(&self) -> u32 {
288 self.as_inner().mode()
289 }
d9579d0f 290
7453a54e
SL
291 fn set_mode(&mut self, mode: u32) {
292 *self = Permissions::from_inner(FromInner::from_inner(mode));
d9579d0f
AL
293 }
294
7453a54e
SL
295 fn from_mode(mode: u32) -> Permissions {
296 Permissions::from_inner(FromInner::from_inner(mode))
d9579d0f
AL
297 }
298}
299
83c7162d 300/// Unix-specific extensions to [`fs::OpenOptions`].
d9579d0f
AL
301#[stable(feature = "fs_ext", since = "1.1.0")]
302pub trait OpenOptionsExt {
303 /// Sets the mode bits that a new file will be created with.
304 ///
60c5eb7d 305 /// If a new file is created as part of an `OpenOptions::open` call then this
d9579d0f 306 /// specified `mode` will be used as the permission bits for the new file.
7453a54e 307 /// If no `mode` is set, the default of `0o666` will be used.
60c5eb7d 308 /// The operating system masks out bits with the system's `umask`, to produce
7453a54e 309 /// the final permissions.
5bcae85e
SL
310 ///
311 /// # Examples
312 ///
041b39d2 313 /// ```no_run
5bcae85e
SL
314 /// use std::fs::OpenOptions;
315 /// use std::os::unix::fs::OpenOptionsExt;
316 ///
041b39d2 317 /// # fn main() {
5bcae85e
SL
318 /// let mut options = OpenOptions::new();
319 /// options.mode(0o644); // Give read/write for owner and read for others.
320 /// let file = options.open("foo.txt");
041b39d2 321 /// # }
5bcae85e 322 /// ```
d9579d0f 323 #[stable(feature = "fs_ext", since = "1.1.0")]
7453a54e
SL
324 fn mode(&mut self, mode: u32) -> &mut Self;
325
3b2f2976 326 /// Pass custom flags to the `flags` argument of `open`.
7453a54e
SL
327 ///
328 /// The bits that define the access mode are masked out with `O_ACCMODE`, to
329 /// ensure they do not interfere with the access mode set by Rusts options.
330 ///
331 /// Custom flags can only set flags, not remove flags set by Rusts options.
332 /// This options overwrites any previously set custom flags.
333 ///
334 /// # Examples
335 ///
041b39d2 336 /// ```no_run
0731742a 337 /// # #![feature(rustc_private)]
7453a54e
SL
338 /// extern crate libc;
339 /// use std::fs::OpenOptions;
340 /// use std::os::unix::fs::OpenOptionsExt;
341 ///
041b39d2 342 /// # fn main() {
7453a54e
SL
343 /// let mut options = OpenOptions::new();
344 /// options.write(true);
345 /// if cfg!(unix) {
346 /// options.custom_flags(libc::O_NOFOLLOW);
347 /// }
348 /// let file = options.open("foo.txt");
041b39d2 349 /// # }
7453a54e 350 /// ```
a7813a04 351 #[stable(feature = "open_options_ext", since = "1.10.0")]
7453a54e 352 fn custom_flags(&mut self, flags: i32) -> &mut Self;
d9579d0f
AL
353}
354
355#[stable(feature = "fs_ext", since = "1.1.0")]
356impl OpenOptionsExt for OpenOptions {
7453a54e 357 fn mode(&mut self, mode: u32) -> &mut OpenOptions {
60c5eb7d
XL
358 self.as_inner_mut().mode(mode);
359 self
d9579d0f 360 }
7453a54e
SL
361
362 fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
60c5eb7d
XL
363 self.as_inner_mut().custom_flags(flags);
364 self
7453a54e 365 }
d9579d0f
AL
366}
367
83c7162d 368/// Unix-specific extensions to [`fs::Metadata`].
d9579d0f
AL
369#[stable(feature = "metadata_ext", since = "1.1.0")]
370pub trait MetadataExt {
abe05a73
XL
371 /// Returns the ID of the device containing the file.
372 ///
373 /// # Examples
374 ///
375 /// ```no_run
0531ce1d 376 /// use std::io;
abe05a73
XL
377 /// use std::fs;
378 /// use std::os::unix::fs::MetadataExt;
379 ///
0531ce1d
XL
380 /// fn main() -> io::Result<()> {
381 /// let meta = fs::metadata("some_file")?;
382 /// let dev_id = meta.dev();
383 /// Ok(())
384 /// }
abe05a73 385 /// ```
d9579d0f 386 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 387 fn dev(&self) -> u64;
abe05a73
XL
388 /// Returns the inode number.
389 ///
390 /// # Examples
391 ///
392 /// ```no_run
393 /// use std::fs;
394 /// use std::os::unix::fs::MetadataExt;
0531ce1d 395 /// use std::io;
abe05a73 396 ///
0531ce1d
XL
397 /// fn main() -> io::Result<()> {
398 /// let meta = fs::metadata("some_file")?;
399 /// let inode = meta.ino();
400 /// Ok(())
401 /// }
abe05a73 402 /// ```
d9579d0f 403 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 404 fn ino(&self) -> u64;
abe05a73
XL
405 /// Returns the rights applied to this file.
406 ///
407 /// # Examples
408 ///
409 /// ```no_run
410 /// use std::fs;
411 /// use std::os::unix::fs::MetadataExt;
0531ce1d
XL
412 /// use std::io;
413 ///
414 /// fn main() -> io::Result<()> {
415 /// let meta = fs::metadata("some_file")?;
416 /// let mode = meta.mode();
417 /// let user_has_write_access = mode & 0o200;
418 /// let user_has_read_write_access = mode & 0o600;
419 /// let group_has_read_access = mode & 0o040;
420 /// let others_have_exec_access = mode & 0o001;
421 /// Ok(())
422 /// }
abe05a73 423 /// ```
d9579d0f 424 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 425 fn mode(&self) -> u32;
abe05a73
XL
426 /// Returns the number of hard links pointing to this file.
427 ///
428 /// # Examples
429 ///
430 /// ```no_run
431 /// use std::fs;
432 /// use std::os::unix::fs::MetadataExt;
1b1a35ee 433 /// use std::io;
abe05a73 434 ///
0531ce1d
XL
435 /// fn main() -> io::Result<()> {
436 /// let meta = fs::metadata("some_file")?;
437 /// let nb_hard_links = meta.nlink();
438 /// Ok(())
439 /// }
abe05a73 440 /// ```
d9579d0f 441 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 442 fn nlink(&self) -> u64;
abe05a73
XL
443 /// Returns the user ID of the owner of this file.
444 ///
445 /// # Examples
446 ///
447 /// ```no_run
448 /// use std::fs;
449 /// use std::os::unix::fs::MetadataExt;
0531ce1d 450 /// use std::io;
abe05a73 451 ///
0531ce1d
XL
452 /// fn main() -> io::Result<()> {
453 /// let meta = fs::metadata("some_file")?;
454 /// let user_id = meta.uid();
455 /// Ok(())
456 /// }
abe05a73 457 /// ```
d9579d0f 458 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 459 fn uid(&self) -> u32;
abe05a73
XL
460 /// Returns the group ID of the owner of this file.
461 ///
462 /// # Examples
463 ///
464 /// ```no_run
465 /// use std::fs;
466 /// use std::os::unix::fs::MetadataExt;
0531ce1d 467 /// use std::io;
abe05a73 468 ///
0531ce1d
XL
469 /// fn main() -> io::Result<()> {
470 /// let meta = fs::metadata("some_file")?;
471 /// let group_id = meta.gid();
472 /// Ok(())
473 /// }
abe05a73 474 /// ```
d9579d0f 475 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 476 fn gid(&self) -> u32;
abe05a73
XL
477 /// Returns the device ID of this file (if it is a special one).
478 ///
479 /// # Examples
480 ///
481 /// ```no_run
482 /// use std::fs;
483 /// use std::os::unix::fs::MetadataExt;
0531ce1d 484 /// use std::io;
abe05a73 485 ///
0531ce1d
XL
486 /// fn main() -> io::Result<()> {
487 /// let meta = fs::metadata("some_file")?;
488 /// let device_id = meta.rdev();
489 /// Ok(())
490 /// }
abe05a73 491 /// ```
d9579d0f 492 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 493 fn rdev(&self) -> u64;
abe05a73
XL
494 /// Returns the total size of this file in bytes.
495 ///
496 /// # Examples
497 ///
498 /// ```no_run
499 /// use std::fs;
500 /// use std::os::unix::fs::MetadataExt;
0531ce1d 501 /// use std::io;
abe05a73 502 ///
0531ce1d
XL
503 /// fn main() -> io::Result<()> {
504 /// let meta = fs::metadata("some_file")?;
505 /// let file_size = meta.size();
506 /// Ok(())
507 /// }
abe05a73 508 /// ```
d9579d0f 509 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 510 fn size(&self) -> u64;
a1dfa0c6 511 /// Returns the last access time of the file, in seconds since Unix Epoch.
abe05a73
XL
512 ///
513 /// # Examples
514 ///
515 /// ```no_run
516 /// use std::fs;
517 /// use std::os::unix::fs::MetadataExt;
0531ce1d 518 /// use std::io;
abe05a73 519 ///
0531ce1d
XL
520 /// fn main() -> io::Result<()> {
521 /// let meta = fs::metadata("some_file")?;
522 /// let last_access_time = meta.atime();
523 /// Ok(())
524 /// }
abe05a73 525 /// ```
d9579d0f 526 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 527 fn atime(&self) -> i64;
a1dfa0c6
XL
528 /// Returns the last access time of the file, in nanoseconds since [`atime`].
529 ///
3dfed10e 530 /// [`atime`]: MetadataExt::atime
abe05a73
XL
531 ///
532 /// # Examples
533 ///
534 /// ```no_run
535 /// use std::fs;
536 /// use std::os::unix::fs::MetadataExt;
0531ce1d 537 /// use std::io;
abe05a73 538 ///
0531ce1d
XL
539 /// fn main() -> io::Result<()> {
540 /// let meta = fs::metadata("some_file")?;
541 /// let nano_last_access_time = meta.atime_nsec();
542 /// Ok(())
543 /// }
abe05a73 544 /// ```
d9579d0f 545 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 546 fn atime_nsec(&self) -> i64;
a1dfa0c6 547 /// Returns the last modification time of the file, in seconds since Unix Epoch.
abe05a73
XL
548 ///
549 /// # Examples
550 ///
551 /// ```no_run
552 /// use std::fs;
553 /// use std::os::unix::fs::MetadataExt;
0531ce1d 554 /// use std::io;
abe05a73 555 ///
0531ce1d
XL
556 /// fn main() -> io::Result<()> {
557 /// let meta = fs::metadata("some_file")?;
558 /// let last_modification_time = meta.mtime();
559 /// Ok(())
560 /// }
abe05a73 561 /// ```
d9579d0f 562 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 563 fn mtime(&self) -> i64;
a1dfa0c6
XL
564 /// Returns the last modification time of the file, in nanoseconds since [`mtime`].
565 ///
3dfed10e 566 /// [`mtime`]: MetadataExt::mtime
abe05a73
XL
567 ///
568 /// # Examples
569 ///
570 /// ```no_run
571 /// use std::fs;
572 /// use std::os::unix::fs::MetadataExt;
0531ce1d 573 /// use std::io;
abe05a73 574 ///
0531ce1d
XL
575 /// fn main() -> io::Result<()> {
576 /// let meta = fs::metadata("some_file")?;
577 /// let nano_last_modification_time = meta.mtime_nsec();
578 /// Ok(())
579 /// }
abe05a73 580 /// ```
d9579d0f 581 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 582 fn mtime_nsec(&self) -> i64;
a1dfa0c6 583 /// Returns the last status change time of the file, in seconds since Unix Epoch.
abe05a73
XL
584 ///
585 /// # Examples
586 ///
587 /// ```no_run
588 /// use std::fs;
589 /// use std::os::unix::fs::MetadataExt;
0531ce1d 590 /// use std::io;
abe05a73 591 ///
0531ce1d
XL
592 /// fn main() -> io::Result<()> {
593 /// let meta = fs::metadata("some_file")?;
594 /// let last_status_change_time = meta.ctime();
595 /// Ok(())
596 /// }
abe05a73 597 /// ```
d9579d0f 598 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 599 fn ctime(&self) -> i64;
a1dfa0c6
XL
600 /// Returns the last status change time of the file, in nanoseconds since [`ctime`].
601 ///
3dfed10e 602 /// [`ctime`]: MetadataExt::ctime
abe05a73
XL
603 ///
604 /// # Examples
605 ///
606 /// ```no_run
607 /// use std::fs;
608 /// use std::os::unix::fs::MetadataExt;
0531ce1d 609 /// use std::io;
abe05a73 610 ///
0531ce1d
XL
611 /// fn main() -> io::Result<()> {
612 /// let meta = fs::metadata("some_file")?;
613 /// let nano_last_status_change_time = meta.ctime_nsec();
614 /// Ok(())
615 /// }
abe05a73 616 /// ```
d9579d0f 617 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 618 fn ctime_nsec(&self) -> i64;
3dfed10e 619 /// Returns the block size for filesystem I/O.
abe05a73
XL
620 ///
621 /// # Examples
622 ///
623 /// ```no_run
624 /// use std::fs;
625 /// use std::os::unix::fs::MetadataExt;
0531ce1d 626 /// use std::io;
abe05a73 627 ///
0531ce1d
XL
628 /// fn main() -> io::Result<()> {
629 /// let meta = fs::metadata("some_file")?;
3dfed10e 630 /// let block_size = meta.blksize();
0531ce1d
XL
631 /// Ok(())
632 /// }
abe05a73 633 /// ```
d9579d0f 634 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 635 fn blksize(&self) -> u64;
abe05a73
XL
636 /// Returns the number of blocks allocated to the file, in 512-byte units.
637 ///
638 /// Please note that this may be smaller than `st_size / 512` when the file has holes.
639 ///
640 /// # Examples
641 ///
642 /// ```no_run
643 /// use std::fs;
644 /// use std::os::unix::fs::MetadataExt;
0531ce1d 645 /// use std::io;
abe05a73 646 ///
0531ce1d
XL
647 /// fn main() -> io::Result<()> {
648 /// let meta = fs::metadata("some_file")?;
649 /// let blocks = meta.blocks();
650 /// Ok(())
651 /// }
abe05a73 652 /// ```
d9579d0f 653 #[stable(feature = "metadata_ext", since = "1.1.0")]
7453a54e 654 fn blocks(&self) -> u64;
29967ef6
XL
655 #[cfg(target_os = "vxworks")]
656 #[stable(feature = "metadata_ext", since = "1.1.0")]
657 fn attrib(&self) -> u8;
d9579d0f
AL
658}
659
92a42be0 660#[stable(feature = "metadata_ext", since = "1.1.0")]
d9579d0f 661impl MetadataExt for fs::Metadata {
60c5eb7d
XL
662 fn dev(&self) -> u64 {
663 self.st_dev()
664 }
665 fn ino(&self) -> u64 {
666 self.st_ino()
667 }
668 fn mode(&self) -> u32 {
669 self.st_mode()
670 }
671 fn nlink(&self) -> u64 {
672 self.st_nlink()
673 }
674 fn uid(&self) -> u32 {
675 self.st_uid()
676 }
677 fn gid(&self) -> u32 {
678 self.st_gid()
679 }
680 fn rdev(&self) -> u64 {
681 self.st_rdev()
682 }
683 fn size(&self) -> u64 {
684 self.st_size()
685 }
686 fn atime(&self) -> i64 {
687 self.st_atime()
688 }
689 fn atime_nsec(&self) -> i64 {
690 self.st_atime_nsec()
691 }
692 fn mtime(&self) -> i64 {
693 self.st_mtime()
694 }
695 fn mtime_nsec(&self) -> i64 {
696 self.st_mtime_nsec()
697 }
698 fn ctime(&self) -> i64 {
699 self.st_ctime()
700 }
701 fn ctime_nsec(&self) -> i64 {
702 self.st_ctime_nsec()
703 }
704 fn blksize(&self) -> u64 {
705 self.st_blksize()
706 }
707 fn blocks(&self) -> u64 {
708 self.st_blocks()
709 }
29967ef6
XL
710 #[cfg(target_os = "vxworks")]
711 fn attrib(&self) -> u8 {
712 self.st_attrib()
713 }
d9579d0f
AL
714}
715
3dfed10e 716/// Unix-specific extensions for [`fs::FileType`].
83c7162d
XL
717///
718/// Adds support for special Unix file types such as block/character devices,
719/// pipes, and sockets.
b039eaaf 720#[stable(feature = "file_type_ext", since = "1.5.0")]
c1a9b12d 721pub trait FileTypeExt {
9fa01778 722 /// Returns `true` if this file type is a block device.
abe05a73
XL
723 ///
724 /// # Examples
725 ///
0531ce1d 726 /// ```no_run
abe05a73
XL
727 /// use std::fs;
728 /// use std::os::unix::fs::FileTypeExt;
0531ce1d 729 /// use std::io;
abe05a73 730 ///
0531ce1d
XL
731 /// fn main() -> io::Result<()> {
732 /// let meta = fs::metadata("block_device_file")?;
733 /// let file_type = meta.file_type();
734 /// assert!(file_type.is_block_device());
735 /// Ok(())
736 /// }
abe05a73 737 /// ```
b039eaaf 738 #[stable(feature = "file_type_ext", since = "1.5.0")]
c1a9b12d 739 fn is_block_device(&self) -> bool;
9fa01778 740 /// Returns `true` if this file type is a char device.
abe05a73
XL
741 ///
742 /// # Examples
743 ///
0531ce1d 744 /// ```no_run
abe05a73
XL
745 /// use std::fs;
746 /// use std::os::unix::fs::FileTypeExt;
0531ce1d 747 /// use std::io;
abe05a73 748 ///
0531ce1d
XL
749 /// fn main() -> io::Result<()> {
750 /// let meta = fs::metadata("char_device_file")?;
751 /// let file_type = meta.file_type();
752 /// assert!(file_type.is_char_device());
753 /// Ok(())
754 /// }
abe05a73 755 /// ```
b039eaaf 756 #[stable(feature = "file_type_ext", since = "1.5.0")]
c1a9b12d 757 fn is_char_device(&self) -> bool;
9fa01778 758 /// Returns `true` if this file type is a fifo.
abe05a73
XL
759 ///
760 /// # Examples
761 ///
0531ce1d 762 /// ```no_run
abe05a73
XL
763 /// use std::fs;
764 /// use std::os::unix::fs::FileTypeExt;
0531ce1d 765 /// use std::io;
abe05a73 766 ///
0531ce1d
XL
767 /// fn main() -> io::Result<()> {
768 /// let meta = fs::metadata("fifo_file")?;
769 /// let file_type = meta.file_type();
770 /// assert!(file_type.is_fifo());
771 /// Ok(())
772 /// }
abe05a73 773 /// ```
b039eaaf 774 #[stable(feature = "file_type_ext", since = "1.5.0")]
c1a9b12d 775 fn is_fifo(&self) -> bool;
9fa01778 776 /// Returns `true` if this file type is a socket.
abe05a73
XL
777 ///
778 /// # Examples
779 ///
0531ce1d 780 /// ```no_run
abe05a73
XL
781 /// use std::fs;
782 /// use std::os::unix::fs::FileTypeExt;
0531ce1d 783 /// use std::io;
abe05a73 784 ///
0531ce1d
XL
785 /// fn main() -> io::Result<()> {
786 /// let meta = fs::metadata("unix.socket")?;
787 /// let file_type = meta.file_type();
788 /// assert!(file_type.is_socket());
789 /// Ok(())
790 /// }
abe05a73 791 /// ```
b039eaaf 792 #[stable(feature = "file_type_ext", since = "1.5.0")]
c1a9b12d
SL
793 fn is_socket(&self) -> bool;
794}
795
b039eaaf 796#[stable(feature = "file_type_ext", since = "1.5.0")]
c1a9b12d 797impl FileTypeExt for fs::FileType {
60c5eb7d
XL
798 fn is_block_device(&self) -> bool {
799 self.as_inner().is(libc::S_IFBLK)
800 }
801 fn is_char_device(&self) -> bool {
802 self.as_inner().is(libc::S_IFCHR)
803 }
804 fn is_fifo(&self) -> bool {
805 self.as_inner().is(libc::S_IFIFO)
806 }
807 fn is_socket(&self) -> bool {
808 self.as_inner().is(libc::S_IFSOCK)
809 }
c1a9b12d
SL
810}
811
abe05a73 812/// Unix-specific extension methods for [`fs::DirEntry`].
d9579d0f
AL
813#[stable(feature = "dir_entry_ext", since = "1.1.0")]
814pub trait DirEntryExt {
815 /// Returns the underlying `d_ino` field in the contained `dirent`
816 /// structure.
5bcae85e
SL
817 ///
818 /// # Examples
819 ///
820 /// ```
821 /// use std::fs;
822 /// use std::os::unix::fs::DirEntryExt;
823 ///
824 /// if let Ok(entries) = fs::read_dir(".") {
825 /// for entry in entries {
826 /// if let Ok(entry) = entry {
827 /// // Here, `entry` is a `DirEntry`.
828 /// println!("{:?}: {}", entry.file_name(), entry.ino());
829 /// }
830 /// }
831 /// }
832 /// ```
d9579d0f 833 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
7453a54e 834 fn ino(&self) -> u64;
d9579d0f
AL
835}
836
92a42be0 837#[stable(feature = "dir_entry_ext", since = "1.1.0")]
d9579d0f 838impl DirEntryExt for fs::DirEntry {
60c5eb7d
XL
839 fn ino(&self) -> u64 {
840 self.as_inner().ino()
841 }
d9579d0f
AL
842}
843
136023e0
XL
844/// Sealed Unix-specific extension methods for [`fs::DirEntry`].
845#[unstable(feature = "dir_entry_ext2", issue = "85573")]
846pub trait DirEntryExt2: Sealed {
847 /// Returns a reference to the underlying `OsStr` of this entry's filename.
848 ///
849 /// # Examples
850 ///
851 /// ```
852 /// #![feature(dir_entry_ext2)]
853 /// use std::os::unix::fs::DirEntryExt2;
854 /// use std::{fs, io};
855 ///
856 /// fn main() -> io::Result<()> {
857 /// let mut entries = fs::read_dir(".")?.collect::<Result<Vec<_>, io::Error>>()?;
858 /// entries.sort_unstable_by(|a, b| a.file_name_ref().cmp(b.file_name_ref()));
859 ///
860 /// for p in entries {
861 /// println!("{:?}", p);
862 /// }
863 ///
864 /// Ok(())
865 /// }
866 /// ```
867 fn file_name_ref(&self) -> &OsStr;
868}
869
870/// Allows extension traits within `std`.
871#[unstable(feature = "sealed", issue = "none")]
872impl Sealed for fs::DirEntry {}
873
874#[unstable(feature = "dir_entry_ext2", issue = "85573")]
875impl DirEntryExt2 for fs::DirEntry {
876 fn file_name_ref(&self) -> &OsStr {
877 self.as_inner().file_name_os_str()
878 }
879}
880
d9579d0f
AL
881/// Creates a new symbolic link on the filesystem.
882///
fc512014 883/// The `link` path will be a symbolic link pointing to the `original` path.
d9579d0f 884///
d9579d0f
AL
885/// # Examples
886///
0531ce1d 887/// ```no_run
d9579d0f
AL
888/// use std::os::unix::fs;
889///
0531ce1d
XL
890/// fn main() -> std::io::Result<()> {
891/// fs::symlink("a.txt", "b.txt")?;
892/// Ok(())
893/// }
d9579d0f 894/// ```
62682a34 895#[stable(feature = "symlink", since = "1.1.0")]
fc512014
XL
896pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
897 sys::fs::symlink(original.as_ref(), link.as_ref())
d9579d0f
AL
898}
899
83c7162d 900/// Unix-specific extensions to [`fs::DirBuilder`].
83c7162d 901#[stable(feature = "dir_builder", since = "1.6.0")]
d9579d0f
AL
902pub trait DirBuilderExt {
903 /// Sets the mode to create new directories with. This option defaults to
904 /// 0o777.
5bcae85e
SL
905 ///
906 /// # Examples
907 ///
041b39d2 908 /// ```no_run
5bcae85e
SL
909 /// use std::fs::DirBuilder;
910 /// use std::os::unix::fs::DirBuilderExt;
911 ///
912 /// let mut builder = DirBuilder::new();
913 /// builder.mode(0o755);
914 /// ```
92a42be0 915 #[stable(feature = "dir_builder", since = "1.6.0")]
7453a54e 916 fn mode(&mut self, mode: u32) -> &mut Self;
d9579d0f
AL
917}
918
92a42be0 919#[stable(feature = "dir_builder", since = "1.6.0")]
d9579d0f 920impl DirBuilderExt for fs::DirBuilder {
7453a54e 921 fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder {
d9579d0f
AL
922 self.as_inner_mut().set_mode(mode);
923 self
924 }
925}
cdc7bbd5
XL
926
927/// Change the root directory of the current process to the specified path.
928///
929/// This typically requires privileges, such as root or a specific capability.
930///
931/// This does not change the current working directory; you should call
932/// [`std::env::set_current_dir`][`crate::env::set_current_dir`] afterwards.
933///
934/// # Examples
935///
936/// ```no_run
cdc7bbd5
XL
937/// use std::os::unix::fs;
938///
939/// fn main() -> std::io::Result<()> {
940/// fs::chroot("/sandbox")?;
941/// std::env::set_current_dir("/")?;
942/// // continue working in sandbox
943/// Ok(())
944/// }
945/// ```
94222f64 946#[stable(feature = "unix_chroot", since = "1.56.0")]
17df50a5 947#[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))]
cdc7bbd5
XL
948pub fn chroot<P: AsRef<Path>>(dir: P) -> io::Result<()> {
949 sys::fs::chroot(dir.as_ref())
950}