Skip to content

Commit 5a430f9

Browse files
committed
add DirEntry API, fixes for other platforms
1 parent c5ac220 commit 5a430f9

File tree

9 files changed

+577
-7
lines changed

9 files changed

+577
-7
lines changed

library/std/src/fs.rs

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2751,6 +2751,178 @@ impl DirEntry {
27512751
pub fn file_name(&self) -> OsString {
27522752
self.0.file_name()
27532753
}
2754+
2755+
/// Attempts to open the file represented by `self` in read-only mode.
2756+
///
2757+
/// # Errors
2758+
///
2759+
/// This function will error whenever [`File::open`] would error, including when `self`
2760+
/// represents a directory.
2761+
///
2762+
/// # Examples
2763+
///
2764+
/// ```no_run
2765+
/// #![feature(dirfd)]
2766+
/// use std::{fs, io::read_to_string};
2767+
///
2768+
/// if let Ok(entries) = fs::read_dir(".") {
2769+
/// for entry in entries {
2770+
/// if let Ok(entry) = entry {
2771+
/// // Here, `entry` is a `DirEntry`.
2772+
/// if let Ok(file) = entry.open_file() && let Ok(text) = read_to_string(file) {
2773+
/// println!("{}", text);
2774+
/// }
2775+
/// }
2776+
/// }
2777+
/// }
2778+
/// ```
2779+
#[unstable(feature = "dirfd", issue = "120426")]
2780+
pub fn open_file(&self) -> io::Result<File> {
2781+
self.0.open_file().map(|inner| File { inner })
2782+
}
2783+
2784+
/// Attempts to open the file represented by `self` with the options specified by `opts`.
2785+
///
2786+
/// # Errors
2787+
///
2788+
/// This function will error whenever [`OpenOptions::open`] would error, including when `self`
2789+
/// represents a directory.
2790+
///
2791+
/// # Examples
2792+
///
2793+
/// ```no_run
2794+
/// #![feature(dirfd)]
2795+
/// use std::{fs, io::Write};
2796+
///
2797+
/// if let Ok(entries) = fs::read_dir(".") {
2798+
/// for entry in entries {
2799+
/// if let Ok(entry) = entry {
2800+
/// // Here, `entry` is a `DirEntry`.
2801+
/// if let Ok(mut file) = entry.open_file_with(fs::OpenOptions::new().write(true)) {
2802+
/// let _ = file.write(b"foo");
2803+
/// }
2804+
/// }
2805+
/// }
2806+
/// }
2807+
/// ```
2808+
#[unstable(feature = "dirfd", issue = "120426")]
2809+
pub fn open_file_with(&self, opts: &OpenOptions) -> io::Result<File> {
2810+
self.0.open_file_with(&opts.0).map(|inner| File { inner })
2811+
}
2812+
2813+
/// Attempts to open the directory represented by `self` in read-only mode.
2814+
///
2815+
/// # Errors
2816+
///
2817+
/// This function will error whenever [`Dir::new`] would error, including when `self`
2818+
/// represents a file.
2819+
///
2820+
/// # Examples
2821+
///
2822+
/// ```no_run
2823+
/// #![feature(dirfd)]
2824+
/// use std::{fs, io::read_to_string};
2825+
///
2826+
/// if let Ok(entries) = fs::read_dir(".") {
2827+
/// for entry in entries {
2828+
/// if let Ok(entry) = entry {
2829+
/// // Here, `entry` is a `DirEntry`.
2830+
/// if let Ok(dir) = entry.open_dir() && let Ok(file) = dir.open("foo") && let Ok(text) = read_to_string(file) {
2831+
/// println!("{}", text);
2832+
/// }
2833+
/// }
2834+
/// }
2835+
/// }
2836+
/// ```
2837+
#[unstable(feature = "dirfd", issue = "120426")]
2838+
pub fn open_dir(&self) -> io::Result<Dir> {
2839+
self.0.open_dir().map(|inner| Dir { inner })
2840+
}
2841+
2842+
/// Attempts to open the directory represented by `self` with the options specified by `opts`.
2843+
///
2844+
/// # Errors
2845+
///
2846+
/// This function will error whenever [`Dir::new_with`] would error, including when `self`
2847+
/// represents a file.
2848+
///
2849+
/// # Examples
2850+
///
2851+
/// ```no_run
2852+
/// #![feature(dirfd)]
2853+
/// use std::fs;
2854+
///
2855+
/// if let Ok(entries) = fs::read_dir(".") {
2856+
/// for entry in entries {
2857+
/// if let Ok(entry) = entry {
2858+
/// // Here, `entry` is a `DirEntry`.
2859+
/// if let Ok(dir) = entry.open_dir_with(fs::OpenOptions::new().write(true)) {
2860+
/// let _ = dir.remove_file("foo");
2861+
/// }
2862+
/// }
2863+
/// }
2864+
/// }
2865+
/// ```
2866+
#[unstable(feature = "dirfd", issue = "120426")]
2867+
pub fn open_dir_with(&self, opts: &OpenOptions) -> io::Result<Dir> {
2868+
self.0.open_dir_with(&opts.0).map(|inner| Dir { inner })
2869+
}
2870+
2871+
/// Attempts to remove the file represented by `self`.
2872+
///
2873+
/// # Errors
2874+
///
2875+
/// This function will return an error whenever [`remove_file`] would error.
2876+
///
2877+
/// # Examples
2878+
///
2879+
/// ```no_run
2880+
/// #![feature(dirfd)]
2881+
/// use std::fs;
2882+
///
2883+
/// if let Ok(entries) = fs::read_dir(".") {
2884+
/// for entry in entries {
2885+
/// if let Ok(entry) = entry {
2886+
/// // Here, `entry` is a `DirEntry`.
2887+
/// if let Ok(ty) = entry.file_type() && ty.is_file() {
2888+
/// let _ = entry.remove_file();
2889+
/// }
2890+
/// }
2891+
/// }
2892+
/// }
2893+
/// ```
2894+
#[unstable(feature = "dirfd", issue = "120426")]
2895+
pub fn remove_file(&self) -> io::Result<()> {
2896+
self.0.remove_file()
2897+
}
2898+
2899+
/// Attempts to remove the directory represented by `self`.
2900+
///
2901+
/// # Errors
2902+
///
2903+
/// This function will return an error whenever [`remove_dir`] would error.
2904+
///
2905+
/// # Examples
2906+
///
2907+
/// ```no_run
2908+
/// #![feature(dirfd)]
2909+
/// use std::fs;
2910+
///
2911+
/// if let Ok(entries) = fs::read_dir(".") {
2912+
/// for entry in entries {
2913+
/// if let Ok(entry) = entry {
2914+
/// // Here, `entry` is a `DirEntry`.
2915+
/// if let Ok(ty) = entry.file_type() && ty.is_dir() {
2916+
/// let _ = entry.remove_dir();
2917+
/// }
2918+
/// }
2919+
/// }
2920+
/// }
2921+
/// ```
2922+
#[unstable(feature = "dirfd", issue = "120426")]
2923+
pub fn remove_dir(&self) -> io::Result<()> {
2924+
self.0.remove_dir()
2925+
}
27542926
}
27552927

27562928
#[stable(feature = "dir_entry_debug", since = "1.13.0")]

library/std/src/sys/fs/common.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#![allow(dead_code)] // not used on all platforms
22

33
use crate::fmt;
4-
use crate::fs::{self, File, OpenOptions, create_dir, remove_dir, remove_file, rename};
4+
use crate::fs::{self, create_dir, remove_dir, remove_file, rename};
55
use crate::io::{self, Error, ErrorKind};
66
use crate::path::{Path, PathBuf};
7+
use crate::sys::fs::{File, OpenOptions};
78
use crate::sys_common::ignore_notfound;
89

910
pub(crate) const NOT_FILE_ERROR: Error = io::const_error!(
@@ -73,18 +74,32 @@ impl Dir {
7374
Ok(Self { path: path.as_ref().to_path_buf() })
7475
}
7576

77+
pub fn new_for_traversal<P: AsRef<Path>>(path: P) -> io::Result<Self> {
78+
Ok(Self { path: path.as_ref().to_path_buf() })
79+
}
80+
7681
pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
77-
File::open(self.path.join(path))
82+
let mut opts = OpenOptions::new();
83+
opts.read(true);
84+
File::open(&self.path.join(path), &opts)
7885
}
7986

8087
pub fn open_with<P: AsRef<Path>>(&self, path: P, opts: &OpenOptions) -> io::Result<File> {
81-
opts.open(self.path.join(path))
88+
File::open(&self.path.join(path), opts)
8289
}
8390

8491
pub fn create_dir<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
8592
create_dir(self.path.join(path))
8693
}
8794

95+
pub fn open_dir<P: AsRef<Path>>(&self, path: P) -> io::Result<Self> {
96+
Self::new(self.path.join(path))
97+
}
98+
99+
pub fn open_dir_with<P: AsRef<Path>>(&self, path: P, opts: &OpenOptions) -> io::Result<Self> {
100+
Self::new_with(self.path.join(path), opts)
101+
}
102+
88103
pub fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
89104
remove_file(self.path.join(path))
90105
}

library/std/src/sys/fs/hermit.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::sync::Arc;
1212
use crate::sys::common::small_c_string::run_path_with_cstr;
1313
use crate::sys::fd::FileDesc;
1414
pub use crate::sys::fs::common::{Dir, copy, exists};
15+
use crate::sys::fs::{remove_dir, remove_file};
1516
use crate::sys::time::SystemTime;
1617
use crate::sys::{cvt, unsupported, unsupported_err};
1718
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
@@ -252,6 +253,32 @@ impl DirEntry {
252253
pub fn file_name_os_str(&self) -> &OsStr {
253254
self.name.as_os_str()
254255
}
256+
257+
pub fn open_file(&self) -> io::Result<File> {
258+
let mut opts = OpenOptions::new();
259+
opts.read(true);
260+
File::open(&self.path(), &opts)
261+
}
262+
263+
pub fn open_file_with(&self, opts: &OpenOptions) -> io::Result<File> {
264+
File::open(&self.path(), opts)
265+
}
266+
267+
pub fn open_dir(&self) -> io::Result<Dir> {
268+
Dir::new(self.path())
269+
}
270+
271+
pub fn open_dir_with(&self, opts: &OpenOptions) -> io::Result<Dir> {
272+
Dir::new_with(self.path(), opts)
273+
}
274+
275+
pub fn remove_file(&self) -> io::Result<()> {
276+
remove_file(&self.path())
277+
}
278+
279+
pub fn remove_dir(&self) -> io::Result<()> {
280+
remove_dir(&self.path())
281+
}
255282
}
256283

257284
impl OpenOptions {

library/std/src/sys/fs/solid.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::os::solid::ffi::OsStrExt;
1010
use crate::path::{Path, PathBuf};
1111
use crate::sync::Arc;
1212
pub use crate::sys::fs::common::{Dir, exists};
13+
use crate::sys::fs::{remove_dir, remove_file};
1314
use crate::sys::pal::{abi, error};
1415
use crate::sys::time::SystemTime;
1516
use crate::sys::{unsupported, unsupported_err};
@@ -219,6 +220,32 @@ impl DirEntry {
219220
_ => lstat(&self.path()).map(|m| m.file_type()),
220221
}
221222
}
223+
224+
pub fn open_file(&self) -> io::Result<File> {
225+
let mut opts = OpenOptions::new();
226+
opts.read(true);
227+
File::open(&self.path(), &opts)
228+
}
229+
230+
pub fn open_file_with(&self, opts: &OpenOptions) -> io::Result<File> {
231+
File::open(&self.path(), opts)
232+
}
233+
234+
pub fn open_dir(&self) -> io::Result<Dir> {
235+
Dir::new(self.path())
236+
}
237+
238+
pub fn open_dir_with(&self, opts: &OpenOptions) -> io::Result<Dir> {
239+
Dir::new_with(self.path(), opts)
240+
}
241+
242+
pub fn remove_file(&self) -> io::Result<()> {
243+
remove_file(&self.path())
244+
}
245+
246+
pub fn remove_dir(&self) -> io::Result<()> {
247+
remove_dir(&self.path())
248+
}
222249
}
223250

224251
impl OpenOptions {

library/std/src/sys/fs/uefi.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,22 +122,34 @@ impl Dir {
122122
unsupported()
123123
}
124124

125-
pub fn new_with<P: AsRef<Path>>(_path: P, opts: &OpenOptions) -> io::Result<Self> {
125+
pub fn new_with<P: AsRef<Path>>(_path: P, _opts: &OpenOptions) -> io::Result<Self> {
126+
unsupported()
127+
}
128+
129+
pub fn new_for_traversal<P: AsRef<Path>>(_path: P) -> io::Result<Self> {
126130
unsupported()
127131
}
128132

129133
pub fn open<P: AsRef<Path>>(&self, _path: P) -> io::Result<File> {
130134
self.0
131135
}
132136

133-
pub fn open_with<P: AsRef<Path>>(&self, _path: P, opts: &OpenOptions) -> io::Result<File> {
137+
pub fn open_with<P: AsRef<Path>>(&self, _path: P, _opts: &OpenOptions) -> io::Result<File> {
134138
self.0
135139
}
136140

137141
pub fn create_dir<P: AsRef<Path>>(&self, _path: P) -> io::Result<()> {
138142
self.0
139143
}
140144

145+
pub fn open_dir<P: AsRef<Path>>(&self, _path: P) -> io::Result<Self> {
146+
self.0
147+
}
148+
149+
pub fn open_dir_with<P: AsRef<Path>>(&self, _path: P, _opts: &OpenOptions) -> io::Result<Self> {
150+
self.0
151+
}
152+
141153
pub fn remove_file<P: AsRef<Path>>(&self, _path: P) -> io::Result<()> {
142154
self.0
143155
}
@@ -192,6 +204,30 @@ impl DirEntry {
192204
pub fn file_type(&self) -> io::Result<FileType> {
193205
self.0
194206
}
207+
208+
pub fn open_file(&self) -> io::Result<File> {
209+
self.0
210+
}
211+
212+
pub fn open_file_with(&self, _opts: &OpenOptions) -> io::Result<File> {
213+
self.0
214+
}
215+
216+
pub fn open_dir(&self) -> io::Result<Dir> {
217+
self.0
218+
}
219+
220+
pub fn open_dir_with(&self, _opts: &OpenOptions) -> io::Result<Dir> {
221+
self.0
222+
}
223+
224+
pub fn remove_file(&self) -> io::Result<()> {
225+
self.0
226+
}
227+
228+
pub fn remove_dir(&self) -> io::Result<()> {
229+
self.0
230+
}
195231
}
196232

197233
impl OpenOptions {

0 commit comments

Comments
 (0)