diff --git a/src/hostcalls_impl/fs.rs b/src/hostcalls_impl/fs.rs index 435d0dfff3..8eae1f25ac 100644 --- a/src/hostcalls_impl/fs.rs +++ b/src/hostcalls_impl/fs.rs @@ -468,10 +468,8 @@ pub(crate) unsafe fn path_create_directory( trace!(" | (path_ptr,path_len)='{}'", path); let rights = host::__WASI_RIGHT_PATH_OPEN | host::__WASI_RIGHT_PATH_CREATE_DIRECTORY; - let dirfd = wasi_ctx - .get_fd_entry(dirfd, rights, 0) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let resolved = path_get(dirfd, 0, path, false)?; + let fo = &wasi_ctx.get_fd_entry(dirfd, rights, 0)?.fd_object; + let resolved = path_get(fo, 0, path, false)?; hostcalls_impl::path_create_directory(resolved) } @@ -508,14 +506,14 @@ pub(crate) unsafe fn path_link( trace!(" | (old_path_ptr,old_path_len)='{}'", old_path); trace!(" | (new_path_ptr,new_path_len)='{}'", new_path); - let old_dirfd = wasi_ctx - .get_fd_entry(old_dirfd, host::__WASI_RIGHT_PATH_LINK_SOURCE, 0) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let new_dirfd = wasi_ctx - .get_fd_entry(new_dirfd, host::__WASI_RIGHT_PATH_LINK_TARGET, 0) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let resolved_old = path_get(old_dirfd, 0, old_path, false)?; - let resolved_new = path_get(new_dirfd, 0, new_path, false)?; + let old_fo = &wasi_ctx + .get_fd_entry(old_dirfd, host::__WASI_RIGHT_PATH_LINK_SOURCE, 0)? + .fd_object; + let new_fo = &wasi_ctx + .get_fd_entry(new_dirfd, host::__WASI_RIGHT_PATH_LINK_TARGET, 0)? + .fd_object; + let resolved_old = path_get(old_fo, 0, old_path, false)?; + let resolved_new = path_get(new_fo, 0, new_path, false)?; hostcalls_impl::path_link(resolved_old, resolved_new) } @@ -562,10 +560,10 @@ pub(crate) unsafe fn path_open( let (needed_base, needed_inheriting) = path_open_rights(fs_rights_base, fs_rights_inheriting, oflags, fs_flags); - let dirfd = wasi_ctx - .get_fd_entry(dirfd, needed_base, needed_inheriting) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let resolved = path_get(dirfd, dirflags, path, oflags & host::__WASI_O_CREAT != 0)?; + let fo = &wasi_ctx + .get_fd_entry(dirfd, needed_base, needed_inheriting)? + .fd_object; + let resolved = path_get(fo, dirflags, path, oflags & host::__WASI_O_CREAT != 0)?; // which open mode do we need? let read = fs_rights_base & (host::__WASI_RIGHT_FD_READ | host::__WASI_RIGHT_FD_READDIR) != 0; @@ -654,10 +652,10 @@ pub(crate) unsafe fn path_readlink( trace!(" | (path_ptr,path_len)='{}'", &path); - let dirfd = wasi_ctx - .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_READLINK, 0) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let resolved = path_get(dirfd, 0, &path, false)?; + let fo = &wasi_ctx + .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_READLINK, 0)? + .fd_object; + let resolved = path_get(fo, 0, &path, false)?; let mut buf = dec_slice_of_mut::(memory, buf_ptr, buf_len)?; @@ -699,14 +697,14 @@ pub(crate) unsafe fn path_rename( trace!(" | (old_path_ptr,old_path_len)='{}'", old_path); trace!(" | (new_path_ptr,new_path_len)='{}'", new_path); - let old_dirfd = wasi_ctx - .get_fd_entry(old_dirfd, host::__WASI_RIGHT_PATH_RENAME_SOURCE, 0) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let new_dirfd = wasi_ctx - .get_fd_entry(new_dirfd, host::__WASI_RIGHT_PATH_RENAME_TARGET, 0) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let resolved_old = path_get(old_dirfd, 0, old_path, true)?; - let resolved_new = path_get(new_dirfd, 0, new_path, true)?; + let old_fo = &wasi_ctx + .get_fd_entry(old_dirfd, host::__WASI_RIGHT_PATH_RENAME_SOURCE, 0)? + .fd_object; + let new_fo = &wasi_ctx + .get_fd_entry(new_dirfd, host::__WASI_RIGHT_PATH_RENAME_TARGET, 0)? + .fd_object; + let resolved_old = path_get(old_fo, 0, old_path, true)?; + let resolved_new = path_get(new_fo, 0, new_path, true)?; log::debug!("path_rename resolved_old={:?}", resolved_old); log::debug!("path_rename resolved_new={:?}", resolved_new); @@ -845,10 +843,10 @@ pub(crate) unsafe fn path_filestat_get( trace!(" | (path_ptr,path_len)='{}'", path); - let dirfd = wasi_ctx - .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_FILESTAT_GET, 0) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let resolved = path_get(dirfd, dirflags, path, false)?; + let fo = &wasi_ctx + .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_FILESTAT_GET, 0)? + .fd_object; + let resolved = path_get(fo, dirflags, path, false)?; let host_filestat = hostcalls_impl::path_filestat_get(resolved, dirflags)?; trace!(" | *filestat_ptr={:?}", host_filestat); @@ -887,10 +885,10 @@ pub(crate) unsafe fn path_filestat_set_times( let st_mtim = dec_timestamp(st_mtim); let fst_flags = dec_fstflags(fst_flags); - let dirfd = wasi_ctx - .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_FILESTAT_SET_TIMES, 0) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let resolved = path_get(dirfd, dirflags, path, false)?; + let fo = &wasi_ctx + .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_FILESTAT_SET_TIMES, 0)? + .fd_object; + let resolved = path_get(fo, dirflags, path, false)?; hostcalls_impl::path_filestat_set_times(resolved, dirflags, st_atim, st_mtim, fst_flags) } @@ -922,10 +920,10 @@ pub(crate) unsafe fn path_symlink( trace!(" | (old_path_ptr,old_path_len)='{}'", old_path); trace!(" | (new_path_ptr,new_path_len)='{}'", new_path); - 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, true)?; + let fo = &wasi_ctx + .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_SYMLINK, 0)? + .fd_object; + let resolved_new = path_get(fo, 0, new_path, true)?; hostcalls_impl::path_symlink(old_path, resolved_new) } @@ -949,10 +947,10 @@ pub(crate) unsafe fn path_unlink_file( trace!(" | (path_ptr,path_len)='{}'", path); - let dirfd = wasi_ctx - .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_UNLINK_FILE, 0) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let resolved = path_get(dirfd, 0, path, false)?; + let fo = &wasi_ctx + .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_UNLINK_FILE, 0)? + .fd_object; + let resolved = path_get(fo, 0, path, false)?; hostcalls_impl::path_unlink_file(resolved) } @@ -976,10 +974,10 @@ pub(crate) unsafe fn path_remove_directory( trace!(" | (path_ptr,path_len)='{}'", path); - let dirfd = wasi_ctx - .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_REMOVE_DIRECTORY, 0) - .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let resolved = path_get(dirfd, 0, path, true)?; + let fo = &wasi_ctx + .get_fd_entry(dirfd, host::__WASI_RIGHT_PATH_REMOVE_DIRECTORY, 0)? + .fd_object; + let resolved = path_get(fo, 0, path, true)?; log::debug!("path_remove_directory resolved={:?}", resolved); diff --git a/src/hostcalls_impl/fs_helpers.rs b/src/hostcalls_impl/fs_helpers.rs index 24cc0d0ab1..7cd0aa9fb6 100644 --- a/src/hostcalls_impl/fs_helpers.rs +++ b/src/hostcalls_impl/fs_helpers.rs @@ -2,7 +2,7 @@ use crate::helpers::str_to_cstring; use crate::sys::host_impl; use crate::sys::hostcalls_impl::fs_helpers::*; -use crate::{host, Error, Result}; +use crate::{fdentry::FdObject, host, Error, Result}; use std::ffi::CString; use std::fs::File; use std::path::{Component, Path}; @@ -31,7 +31,7 @@ impl PathGet { /// /// This is a workaround for not having Capsicum support in the OS. pub(crate) fn path_get( - dirfd: &File, + fo: &FdObject, dirflags: host::__wasi_lookupflags_t, path: &str, needs_final_component: bool, @@ -43,7 +43,12 @@ pub(crate) fn path_get( return Err(Error::EILSEQ); } - let dirfd = dirfd.try_clone()?; + if fo.file_type != host::__WASI_FILETYPE_DIRECTORY { + // if `dirfd` doesn't refer to a directory, return `ENOTDIR`. + return Err(Error::ENOTDIR); + } + + let dirfd = fo.descriptor.as_file()?.try_clone()?; // Stack of directory file descriptors. Index 0 always corresponds with the directory provided // to this function. Entering a directory causes a file descriptor to be pushed, while handling