diff --git a/src/sys/windows/hostcalls_impl/fs.rs b/src/sys/windows/hostcalls_impl/fs.rs index a4bc9a9fb7..54b25d7926 100644 --- a/src/sys/windows/hostcalls_impl/fs.rs +++ b/src/sys/windows/hostcalls_impl/fs.rs @@ -213,26 +213,29 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul if old_path.is_dir() && new_path.is_file() { return Err(host::__WASI_ENOTDIR); } - if old_path.is_file() && new_path.is_dir() { - return Err(host::__WASI_EISDIR); - } // TODO handle symlinks fs::rename(&old_path, &new_path).or_else(|e| match e.raw_os_error() { Some(e) => { - if old_path.is_dir() && new_path.is_dir() { - if !dir_is_empty(&new_path).map_err(errno_from_ioerror)? { - Err(host::__WASI_ENOTEMPTY) - } else { - // remove new_path dir and rename - fs::remove_dir(&new_path) - .and_then(|()| fs::rename(old_path, new_path)) - .map_err(errno_from_ioerror) + use winx::winerror::WinError; + + log::debug!("path_rename at rename error code={:?}", e); + match WinError::from_u32(e as u32) { + WinError::ERROR_ACCESS_DENIED => { + // So most likely dealing with new_path == dir. + // Eliminate case old_path == file first. + if old_path.is_file() { + Err(host::__WASI_EISDIR) + } else { + // Ok, let's try removing an empty dir at new_path if it exists + // and is a nonempty dir. + fs::remove_dir(&new_path) + .and_then(|()| fs::rename(old_path, new_path)) + .map_err(errno_from_ioerror) + } } - } else { - log::debug!("path_rename at rename error={:?}", e); - Err(errno_from_host(e)) + e => Err(host_impl::errno_from_win(e)), } } None => { @@ -242,14 +245,6 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul }) } -fn dir_is_empty>(path: P) -> io::Result { - let mut it = std::fs::read_dir(path)?; - match it.next() { - Some(_) => Ok(false), - None => Ok(true), - } -} - pub(crate) fn num_hardlinks(file: &File, _metadata: &Metadata) -> io::Result { Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into()) }