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)
}

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));
}
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
}

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