Skip to content

Commit 2ea12f6

Browse files
committed
add DirEntry API, fixes for other platforms
1 parent f07f7c5 commit 2ea12f6

File tree

9 files changed

+576
-7
lines changed

9 files changed

+576
-7
lines changed

library/std/src/fs.rs

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

27392911
#[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: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ impl Dir {
126126
unsupported()
127127
}
128128

129+
pub fn new_for_traversal<P: AsRef<Path>>(_path: P) -> io::Result<Self> {
130+
unsupported()
131+
}
132+
129133
pub fn open<P: AsRef<Path>>(&self, _path: P) -> io::Result<File> {
130134
self.0
131135
}
@@ -138,6 +142,14 @@ impl Dir {
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)