Implement path_link for Windows. (#1199)

Implement path_link for Windows.
This commit is contained in:
Marcin Mielniczuk
2020-04-03 21:24:38 +02:00
committed by GitHub
parent 7728703ec7
commit f6e3ab03a2
4 changed files with 51 additions and 9 deletions

View File

@@ -69,7 +69,7 @@ impl From<io::Error> for Errno {
winerror::ERROR_DIRECTORY => Self::Notdir,
winerror::ERROR_ALREADY_EXISTS => Self::Exist,
x => {
log::debug!("unknown error value: {}", x);
log::debug!("winerror: unknown error value: {}", x);
Self::Io
}
},

View File

@@ -3,6 +3,7 @@ use crate::fd;
use crate::path::PathGet;
use crate::sys::entry::OsHandle;
use crate::wasi::{types, Errno, Result};
use log::debug;
use std::convert::TryInto;
use std::ffi::{OsStr, OsString};
use std::fs::{File, Metadata, OpenOptions};
@@ -164,11 +165,48 @@ pub(crate) fn create_directory(file: &File, path: &str) -> Result<()> {
}
pub(crate) fn link(
_resolved_old: PathGet,
_resolved_new: PathGet,
_follow_symlinks: bool,
resolved_old: PathGet,
resolved_new: PathGet,
follow_symlinks: bool,
) -> Result<()> {
unimplemented!("path_link")
use std::fs;
let mut old_path = resolved_old.concatenate()?;
let new_path = resolved_new.concatenate()?;
if follow_symlinks {
// in particular, this will return an error if the target path doesn't exist
debug!("Following symlinks for path: {:?}", old_path);
old_path = fs::canonicalize(&old_path).map_err(|e| match e.raw_os_error() {
// fs::canonicalize under Windows will return:
// * ERROR_FILE_NOT_FOUND, if it encounters a dangling symlink
// * ERROR_CANT_RESOLVE_FILENAME, if it encounters a symlink loop
Some(code) if code as u32 == winerror::ERROR_CANT_RESOLVE_FILENAME => Errno::Loop,
_ => e.into(),
})?;
}
fs::hard_link(&old_path, &new_path).or_else(|err| {
match err.raw_os_error() {
Some(code) => {
debug!("path_link at fs::hard_link error code={:?}", code);
match code as u32 {
winerror::ERROR_ACCESS_DENIED => {
// If an attempt is made to create a hard link to a directory, POSIX-compliant
// implementations of link return `EPERM`, but `ERROR_ACCESS_DENIED` is converted
// to `EACCES`. We detect and correct this case here.
if fs::metadata(&old_path).map(|m| m.is_dir()).unwrap_or(false) {
return Err(Errno::Perm);
}
}
_ => {}
}
Err(err.into())
}
None => {
log::debug!("Inconvertible OS error: {}", err);
Err(Errno::Io)
}
}
})
}
pub(crate) fn open(