Fix path_readlink: with a 0-sized buffer should succeed
This commit is contained in:
@@ -580,13 +580,17 @@ pub fn path_readlink(
|
|||||||
Ok(slice) => host_impl::path_from_raw(slice).to_owned(),
|
Ok(slice) => host_impl::path_from_raw(slice).to_owned(),
|
||||||
Err(e) => return enc_errno(e),
|
Err(e) => return enc_errno(e),
|
||||||
};
|
};
|
||||||
let rights = host::__WASI_RIGHT_PATH_READLINK;
|
|
||||||
let mut buf = match dec_slice_of_mut::<u8>(memory, buf_ptr, buf_len) {
|
let mut buf = match dec_slice_of_mut::<u8>(memory, buf_ptr, buf_len) {
|
||||||
Ok(slice) => slice,
|
Ok(slice) => slice,
|
||||||
Err(e) => return enc_errno(e),
|
Err(e) => return enc_errno(e),
|
||||||
};
|
};
|
||||||
let host_bufused =
|
let host_bufused = match hostcalls_impl::path_readlink(
|
||||||
match hostcalls_impl::path_readlink(wasi_ctx, dirfd, path.as_os_str(), rights, &mut buf) {
|
wasi_ctx,
|
||||||
|
dirfd,
|
||||||
|
path.as_os_str(),
|
||||||
|
host::__WASI_RIGHT_PATH_READLINK,
|
||||||
|
&mut buf,
|
||||||
|
) {
|
||||||
Ok(host_bufused) => host_bufused,
|
Ok(host_bufused) => host_bufused,
|
||||||
Err(e) => return enc_errno(e),
|
Err(e) => return enc_errno(e),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -516,18 +516,43 @@ pub(crate) fn path_readlink(
|
|||||||
rights: host::__wasi_rights_t,
|
rights: host::__wasi_rights_t,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
) -> Result<usize, host::__wasi_errno_t> {
|
) -> Result<usize, host::__wasi_errno_t> {
|
||||||
use nix::fcntl::readlinkat;
|
use nix::errno::Errno;
|
||||||
|
|
||||||
let (dir, path) = match path_get(wasi_ctx, dirfd, 0, path, rights, 0, false) {
|
let (dir, path) = match path_get(wasi_ctx, dirfd, 0, path, rights, 0, false) {
|
||||||
Ok((dir, path)) => (dir, path),
|
Ok((dir, path)) => (dir, path),
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
let target_path = match readlinkat(dir, path.as_os_str(), buf) {
|
let path_cstr = match std::ffi::CString::new(path.as_bytes()) {
|
||||||
Err(e) => return Err(host_impl::errno_from_nix(e.as_errno().unwrap())),
|
Ok(path_cstr) => path_cstr,
|
||||||
Ok(target_path) => target_path,
|
Err(_) => return Err(host::__WASI_EINVAL),
|
||||||
};
|
};
|
||||||
Ok(target_path.len())
|
|
||||||
|
// Linux requires that the buffer size is positive, whereas POSIX does not.
|
||||||
|
// Use a fake buffer to store the results if the size is zero.
|
||||||
|
// TODO: instead of using raw libc::readlinkat call here, this should really
|
||||||
|
// be fixed in `nix` crate
|
||||||
|
let fakebuf: &mut [u8] = &mut [0];
|
||||||
|
let buf_len = buf.len();
|
||||||
|
let len = unsafe {
|
||||||
|
libc::readlinkat(
|
||||||
|
dir,
|
||||||
|
path_cstr.as_ptr() as *const libc::c_char,
|
||||||
|
if buf_len == 0 {
|
||||||
|
fakebuf.as_mut_ptr()
|
||||||
|
} else {
|
||||||
|
buf.as_mut_ptr()
|
||||||
|
} as *mut libc::c_char,
|
||||||
|
if buf_len == 0 { fakebuf.len() } else { buf_len },
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if len < 0 {
|
||||||
|
Err(host_impl::errno_from_nix(Errno::last()))
|
||||||
|
} else {
|
||||||
|
let len = len as usize;
|
||||||
|
Ok(if len < buf_len { len } else { buf_len })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn path_rename(
|
pub(crate) fn path_rename(
|
||||||
|
|||||||
Reference in New Issue
Block a user