Fixes path_symlink_trailing_slashes test case (#125)

* Fixes `path_symlink_trailing_slashes` test case

This commit:
* adds a couple `log::debug!` macro calls in and around `path_get`
  for easier future debugging
* changes impl of `path_symlink` hostcall to actually *require*
  the final component (matching the impl of WASI in C)
* ignores the error `__WASI_ENOTDIR` in `path_get`'s `readlinkat` call
  which is not meant to be an error at this stage (i.e., this
  potentially erroneous condition *will be* handled later, in
  one of the layers above)

* Fixes `path_symlink_trailing` slashes on BSD-nixes

This commit:
* makes `path_symlink` host-specific (Linux and BSD-like nixes
  now have their own differing implementations)
* on BSD-like nixes, when `ENOTDIR` is returned from `symlinkat`
  it checks whether the target path contains a trailing slash,
  strips it, and then checks if the target path without the trailing
  slash exists; if yes, then converts the error code to `EEXIST` to
  match Linux/POSIX spec
This commit is contained in:
Jakub Konka
2019-10-17 11:33:56 +02:00
committed by GitHub
parent d458fb6815
commit c3bf04042e
7 changed files with 79 additions and 31 deletions

View File

@@ -927,7 +927,7 @@ pub(crate) unsafe fn path_symlink(
let dirfd = wasi_ctx
.get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_SYMLINK, 0)
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
let resolved_new = path_get(dirfd, 0, new_path, false)?;
let resolved_new = path_get(dirfd, 0, new_path, true)?;
hostcalls_impl::path_symlink(old_path, resolved_new)
}

View File

@@ -57,7 +57,7 @@ pub(crate) fn path_get(
loop {
match path_stack.pop() {
Some(cur_path) => {
log::debug!("cur_path = {:?}", cur_path);
log::debug!("path_get cur_path = {:?}", cur_path);
let ends_with_slash = cur_path.ends_with('/');
let mut components = Path::new(&cur_path).components();
@@ -75,6 +75,8 @@ pub(crate) fn path_get(
path_stack.push(tail);
}
log::debug!("path_get path_stack = {:?}", path_stack);
match head {
Component::Prefix(_) | Component::RootDir => {
// path is absolute!
@@ -169,6 +171,10 @@ pub(crate) fn path_get(
Err(e) => {
if e.as_wasi_errno() != host::__WASI_EINVAL
&& e.as_wasi_errno() != host::__WASI_ENOENT
// this handles the cases when trying to link to
// a destination that already exists, and the target
// path contains a slash
&& e.as_wasi_errno() != host::__WASI_ENOTDIR
{
return Err(e);
}