Move checks into error handling of std::fs::rename (where possible)
This commit is contained in:
@@ -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() {
|
if old_path.is_dir() && new_path.is_file() {
|
||||||
return Err(host::__WASI_ENOTDIR);
|
return Err(host::__WASI_ENOTDIR);
|
||||||
}
|
}
|
||||||
if old_path.is_file() && new_path.is_dir() {
|
|
||||||
return Err(host::__WASI_EISDIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO handle symlinks
|
// TODO handle symlinks
|
||||||
|
|
||||||
fs::rename(&old_path, &new_path).or_else(|e| match e.raw_os_error() {
|
fs::rename(&old_path, &new_path).or_else(|e| match e.raw_os_error() {
|
||||||
Some(e) => {
|
Some(e) => {
|
||||||
if old_path.is_dir() && new_path.is_dir() {
|
use winx::winerror::WinError;
|
||||||
if !dir_is_empty(&new_path).map_err(errno_from_ioerror)? {
|
|
||||||
Err(host::__WASI_ENOTEMPTY)
|
log::debug!("path_rename at rename error code={:?}", e);
|
||||||
} else {
|
match WinError::from_u32(e as u32) {
|
||||||
// remove new_path dir and rename
|
WinError::ERROR_ACCESS_DENIED => {
|
||||||
fs::remove_dir(&new_path)
|
// So most likely dealing with new_path == dir.
|
||||||
.and_then(|()| fs::rename(old_path, new_path))
|
// Eliminate case old_path == file first.
|
||||||
.map_err(errno_from_ioerror)
|
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 {
|
e => Err(host_impl::errno_from_win(e)),
|
||||||
log::debug!("path_rename at rename error={:?}", e);
|
|
||||||
Err(errno_from_host(e))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@@ -242,14 +245,6 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dir_is_empty<P: AsRef<Path>>(path: P) -> io::Result<bool> {
|
|
||||||
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<u64> {
|
pub(crate) fn num_hardlinks(file: &File, _metadata: &Metadata) -> io::Result<u64> {
|
||||||
Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into())
|
Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user