Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion library/std/src/sys/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ pub use imp::{

pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
// FIXME: use with_native_path on all platforms
imp::readdir(path)
#[cfg(not(windows))]
return imp::readdir(path);
#[cfg(windows)]
with_native_path(path, &imp::readdir)
Comment thread
WrldEngine marked this conversation as resolved.
}

pub fn remove_file(path: &Path) -> io::Result<()> {
Expand Down
20 changes: 14 additions & 6 deletions library/std/src/sys/fs/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::ffi::{OsStr, OsString, c_void};
use crate::fs::TryLockError;
use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
use crate::mem::{self, MaybeUninit, offset_of};
use crate::os::windows::ffi::OsStringExt;
use crate::os::windows::io::{AsHandle, BorrowedHandle};
use crate::os::windows::prelude::*;
use crate::path::{Path, PathBuf};
Expand Down Expand Up @@ -1182,18 +1183,25 @@ impl DirBuilder {
}
}

pub fn readdir(p: &Path) -> io::Result<ReadDir> {
pub fn readdir(p: &WCStr) -> io::Result<ReadDir> {
let p = p.to_wchars_with_null_unchecked();
let mut p = p[..p.len() - 1].to_vec();

// We push a `*` to the end of the path which cause the empty path to be
// treated as the current directory. So, for consistency with other platforms,
// we explicitly error on the empty path.
if p.as_os_str().is_empty() {
if p.is_empty() {
// Return an error code consistent with other ways of opening files.
// E.g. fs::metadata or File::open.
return Err(io::Error::from_raw_os_error(c::ERROR_PATH_NOT_FOUND as i32));
}
Comment on lines 1190 to 1197

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment and check should stay the first thing this function does; there is no sense in creating an empty Vec, but then fail here...

let root = p.to_path_buf();
let star = p.join("*");
let path = maybe_verbatim(&star)?;

let root = PathBuf::from(OsString::from_wide(&p));

// Pushing `*` and NUL at the end
p.push(0x005C);
p.push(0x002A);
p.push(0);

unsafe {
let mut wfd: c::WIN32_FIND_DATAW = mem::zeroed();
Expand All @@ -1205,7 +1213,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
// We can pass FIND_FIRST_EX_LARGE_FETCH to dwAdditionalFlags to speed up things more,
// but as we don't know user's use profile of this function, lets be conservative.
let find_handle = c::FindFirstFileExW(
path.as_ptr(),
p.as_ptr(),
c::FindExInfoBasic,
&mut wfd as *mut _ as _,
c::FindExSearchNameMatch,
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/sys/path/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ impl WCStr {
unsafe { &*(s as *const [u16] as *const Self) }
}

pub const fn to_wchars_with_null_unchecked(&self) -> &[u16] {
&self.0
}

Comment on lines +32 to +35

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably just inline this.

pub fn as_ptr(&self) -> *const u16 {
self.0.as_ptr()
}
Expand Down
Loading