@@ -153,6 +153,33 @@ pub enum TryLockError {
153153 WouldBlock ,
154154}
155155
156+ /// An object providing access to a directory on the filesystem.
157+ ///
158+ /// Files are automatically closed when they go out of scope. Errors detected
159+ /// on closing are ignored by the implementation of `Drop`.
160+ ///
161+ /// # Examples
162+ ///
163+ /// Opens a directory and then a file inside it.
164+ ///
165+ /// ```no_run
166+ /// #![feature(dirfd)]
167+ /// use std::{fs::Dir, io::Read};
168+ ///
169+ /// fn main() -> std::io::Result<()> {
170+ /// let dir = Dir::new("foo")?;
171+ /// let mut file = dir.open("bar.txt")?;
172+ /// let mut s = String::new();
173+ /// file.read_to_string(&mut s)?;
174+ /// println!("{}", s);
175+ /// Ok(())
176+ /// }
177+ /// ```
178+ #[ unstable( feature = "dirfd" , issue = "120426" ) ]
179+ pub struct Dir {
180+ inner : fs_imp:: Dir ,
181+ }
182+
156183/// Metadata information about a file.
157184///
158185/// This structure is returned from the [`metadata`] or
@@ -1474,6 +1501,89 @@ impl Seek for Arc<File> {
14741501 }
14751502}
14761503
1504+ impl Dir {
1505+ /// Attempts to open a directory at `path` in read-only mode.
1506+ ///
1507+ /// See [`new_with`] for more options.
1508+ ///
1509+ /// # Errors
1510+ ///
1511+ /// This function will return an error if `path` does not point to an existing directory.
1512+ /// Other errors may also be returned according to [`OpenOptions::open`].
1513+ ///
1514+ /// # Examples
1515+ ///
1516+ /// ```no_run
1517+ /// #![feature(dirfd)]
1518+ /// use std::{fs::Dir, io::Read};
1519+ ///
1520+ /// fn main() -> std::io::Result<()> {
1521+ /// let dir = Dir::new("foo")?;
1522+ /// let mut f = dir.open("bar.txt")?;
1523+ /// let mut data = vec![];
1524+ /// f.read_to_end(&mut data)?;
1525+ /// Ok(())
1526+ /// }
1527+ /// ```
1528+ ///
1529+ /// [`new_with`]: Dir::new_with
1530+ #[ unstable( feature = "dirfd" , issue = "120426" ) ]
1531+ pub fn open < P : AsRef < Path > > ( path : P ) -> io:: Result < Self > {
1532+ fs_imp:: Dir :: open ( path) . map ( |inner| Self { inner } )
1533+ }
1534+
1535+ ///
1536+ /// Attempts to open a file in read-only mode relative to this directory.
1537+ ///
1538+ /// # Errors
1539+ ///
1540+ /// This function will return an error if `path` does not point to an existing file.
1541+ /// Other errors may also be returned according to [`OpenOptions::open`].
1542+ ///
1543+ /// # Examples
1544+ ///
1545+ /// ```no_run
1546+ /// #![feature(dirfd)]
1547+ /// use std::{fs::Dir, io::Read};
1548+ ///
1549+ /// fn main() -> std::io::Result<()> {
1550+ /// let dir = Dir::new("foo")?;
1551+ /// let mut f = dir.open("bar.txt")?;
1552+ /// let mut data = vec![];
1553+ /// f.read_to_end(&mut data)?;
1554+ /// Ok(())
1555+ /// }
1556+ /// ```
1557+ #[ unstable( feature = "dirfd" , issue = "120426" ) ]
1558+ pub fn open_file < P : AsRef < Path > > ( & self , path : P ) -> io:: Result < File > {
1559+ self . inner . open_file ( path) . map ( |f| File { inner : f } )
1560+ }
1561+ }
1562+
1563+ impl AsInner < fs_imp:: Dir > for Dir {
1564+ #[ inline]
1565+ fn as_inner ( & self ) -> & fs_imp:: Dir {
1566+ & self . inner
1567+ }
1568+ }
1569+ impl FromInner < fs_imp:: Dir > for Dir {
1570+ fn from_inner ( f : fs_imp:: Dir ) -> File {
1571+ Dir { inner : f }
1572+ }
1573+ }
1574+ impl IntoInner < fs_imp:: Dir > for Dir {
1575+ fn into_inner ( self ) -> fs_imp:: Dir {
1576+ self . inner
1577+ }
1578+ }
1579+
1580+ #[ unstable( feature = "dirfd" , issue = "120426" ) ]
1581+ impl fmt:: Debug for Dir {
1582+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1583+ self . inner . fmt ( f)
1584+ }
1585+ }
1586+
14771587impl OpenOptions {
14781588 /// Creates a blank new set of options ready for configuration.
14791589 ///
@@ -2440,6 +2550,178 @@ impl DirEntry {
24402550 pub fn file_name ( & self ) -> OsString {
24412551 self . 0 . file_name ( )
24422552 }
2553+
2554+ /// Attempts to open the file represented by `self` in read-only mode.
2555+ ///
2556+ /// # Errors
2557+ ///
2558+ /// This function will error whenever [`File::open`] would error, including when `self`
2559+ /// represents a directory.
2560+ ///
2561+ /// # Examples
2562+ ///
2563+ /// ```no_run
2564+ /// #![feature(dirfd)]
2565+ /// use std::{fs, io::read_to_string};
2566+ ///
2567+ /// if let Ok(entries) = fs::read_dir(".") {
2568+ /// for entry in entries {
2569+ /// if let Ok(entry) = entry {
2570+ /// // Here, `entry` is a `DirEntry`.
2571+ /// if let Ok(file) = entry.open_file() && let Ok(text) = read_to_string(file) {
2572+ /// println!("{}", text);
2573+ /// }
2574+ /// }
2575+ /// }
2576+ /// }
2577+ /// ```
2578+ #[ unstable( feature = "dirfd" , issue = "120426" ) ]
2579+ pub fn open_file ( & self ) -> io:: Result < File > {
2580+ self . 0 . open_file ( ) . map ( |inner| File { inner } )
2581+ }
2582+
2583+ /// Attempts to open the file represented by `self` with the options specified by `opts`.
2584+ ///
2585+ /// # Errors
2586+ ///
2587+ /// This function will error whenever [`OpenOptions::open`] would error, including when `self`
2588+ /// represents a directory.
2589+ ///
2590+ /// # Examples
2591+ ///
2592+ /// ```no_run
2593+ /// #![feature(dirfd)]
2594+ /// use std::{fs, io::Write};
2595+ ///
2596+ /// if let Ok(entries) = fs::read_dir(".") {
2597+ /// for entry in entries {
2598+ /// if let Ok(entry) = entry {
2599+ /// // Here, `entry` is a `DirEntry`.
2600+ /// if let Ok(mut file) = entry.open_file_with(fs::OpenOptions::new().write(true)) {
2601+ /// let _ = file.write(b"foo");
2602+ /// }
2603+ /// }
2604+ /// }
2605+ /// }
2606+ /// ```
2607+ #[ unstable( feature = "dirfd" , issue = "120426" ) ]
2608+ pub fn open_file_with ( & self , opts : & OpenOptions ) -> io:: Result < File > {
2609+ self . 0 . open_file_with ( & opts. 0 ) . map ( |inner| File { inner } )
2610+ }
2611+
2612+ /// Attempts to open the directory represented by `self` in read-only mode.
2613+ ///
2614+ /// # Errors
2615+ ///
2616+ /// This function will error whenever [`Dir::new`] would error, including when `self`
2617+ /// represents a file.
2618+ ///
2619+ /// # Examples
2620+ ///
2621+ /// ```no_run
2622+ /// #![feature(dirfd)]
2623+ /// use std::{fs, io::read_to_string};
2624+ ///
2625+ /// if let Ok(entries) = fs::read_dir(".") {
2626+ /// for entry in entries {
2627+ /// if let Ok(entry) = entry {
2628+ /// // Here, `entry` is a `DirEntry`.
2629+ /// if let Ok(dir) = entry.open_dir() && let Ok(file) = dir.open("foo") && let Ok(text) = read_to_string(file) {
2630+ /// println!("{}", text);
2631+ /// }
2632+ /// }
2633+ /// }
2634+ /// }
2635+ /// ```
2636+ #[ unstable( feature = "dirfd" , issue = "120426" ) ]
2637+ pub fn open_dir ( & self ) -> io:: Result < Dir > {
2638+ self . 0 . open_dir ( ) . map ( |inner| Dir { inner } )
2639+ }
2640+
2641+ /// Attempts to open the directory represented by `self` with the options specified by `opts`.
2642+ ///
2643+ /// # Errors
2644+ ///
2645+ /// This function will error whenever [`Dir::new_with`] would error, including when `self`
2646+ /// represents a file.
2647+ ///
2648+ /// # Examples
2649+ ///
2650+ /// ```no_run
2651+ /// #![feature(dirfd)]
2652+ /// use std::fs;
2653+ ///
2654+ /// if let Ok(entries) = fs::read_dir(".") {
2655+ /// for entry in entries {
2656+ /// if let Ok(entry) = entry {
2657+ /// // Here, `entry` is a `DirEntry`.
2658+ /// if let Ok(dir) = entry.open_dir_with(fs::OpenOptions::new().write(true)) {
2659+ /// let _ = dir.remove_file("foo");
2660+ /// }
2661+ /// }
2662+ /// }
2663+ /// }
2664+ /// ```
2665+ #[ unstable( feature = "dirfd" , issue = "120426" ) ]
2666+ pub fn open_dir_with ( & self , opts : & OpenOptions ) -> io:: Result < Dir > {
2667+ self . 0 . open_dir_with ( & opts. 0 ) . map ( |inner| Dir { inner } )
2668+ }
2669+
2670+ /// Attempts to remove the file represented by `self`.
2671+ ///
2672+ /// # Errors
2673+ ///
2674+ /// This function will return an error whenever [`remove_file`] would error.
2675+ ///
2676+ /// # Examples
2677+ ///
2678+ /// ```no_run
2679+ /// #![feature(dirfd)]
2680+ /// use std::fs;
2681+ ///
2682+ /// if let Ok(entries) = fs::read_dir(".") {
2683+ /// for entry in entries {
2684+ /// if let Ok(entry) = entry {
2685+ /// // Here, `entry` is a `DirEntry`.
2686+ /// if let Ok(ty) = entry.file_type() && ty.is_file() {
2687+ /// let _ = entry.remove_file();
2688+ /// }
2689+ /// }
2690+ /// }
2691+ /// }
2692+ /// ```
2693+ #[ unstable( feature = "dirfd" , issue = "120426" ) ]
2694+ pub fn remove_file ( & self ) -> io:: Result < ( ) > {
2695+ self . 0 . remove_file ( )
2696+ }
2697+
2698+ /// Attempts to remove the directory represented by `self`.
2699+ ///
2700+ /// # Errors
2701+ ///
2702+ /// This function will return an error whenever [`remove_dir`] would error.
2703+ ///
2704+ /// # Examples
2705+ ///
2706+ /// ```no_run
2707+ /// #![feature(dirfd)]
2708+ /// use std::fs;
2709+ ///
2710+ /// if let Ok(entries) = fs::read_dir(".") {
2711+ /// for entry in entries {
2712+ /// if let Ok(entry) = entry {
2713+ /// // Here, `entry` is a `DirEntry`.
2714+ /// if let Ok(ty) = entry.file_type() && ty.is_dir() {
2715+ /// let _ = entry.remove_dir();
2716+ /// }
2717+ /// }
2718+ /// }
2719+ /// }
2720+ /// ```
2721+ #[ unstable( feature = "dirfd" , issue = "120426" ) ]
2722+ pub fn remove_dir ( & self ) -> io:: Result < ( ) > {
2723+ self . 0 . remove_dir ( )
2724+ }
24432725}
24442726
24452727#[ stable( feature = "dir_entry_debug" , since = "1.13.0" ) ]
0 commit comments