Skip to content

Commit

Permalink
add a wasi-test to show a dir_fd always gets ERRNO_BADF on appropriat…
Browse files Browse the repository at this point in the history
…e fd_ operations (#6197)

* add a wasi-test to show a dir_fd always gets ERRNO_BADF on appropriate fd_ operations.

This is a conformance test for the current behavior of preview 1 in wasi-common. It is debatable whether this is the right errno, I think for most of these ERRNO_ISDIR would be more descriptive, but this is the behavior we have.

* Add comments to all the fd op failures explaining closest linux/posix behavior
  • Loading branch information
Pat Hickey committed Apr 12, 2023
1 parent f684a5f commit d1d381e
Showing 1 changed file with 99 additions and 0 deletions.
99 changes: 99 additions & 0 deletions crates/test-programs/wasi-tests/src/bin/dir_fd_op_failures.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use std::{env, process};
use wasi_tests::open_scratch_directory;

unsafe fn test_fd_dir_ops(dir_fd: wasi::Fd) {
let stat = wasi::fd_filestat_get(dir_fd).expect("failed to fdstat");
assert_eq!(stat.filetype, wasi::FILETYPE_DIRECTORY);

let mut read_buf = vec![0; 128].into_boxed_slice();
let iovec = wasi::Iovec {
buf: read_buf.as_mut_ptr(),
buf_len: read_buf.len(),
};
let r = wasi::fd_read(dir_fd, &[iovec]);
// On posix, this fails with ERRNO_ISDIR:
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_read error");

let r = wasi::fd_pread(dir_fd, &[iovec], 0);
// On posix, this fails with ERRNO_ISDIR
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_pread error");

let write_buf = vec![0; 128].into_boxed_slice();
let ciovec = wasi::Ciovec {
buf: write_buf.as_ptr(),
buf_len: write_buf.len(),
};
let r = wasi::fd_write(dir_fd, &[ciovec]);
// Same behavior as specified by POSIX:
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_write error");

let r = wasi::fd_pwrite(dir_fd, &[ciovec], 0);
// Same behavior as specified by POSIX:
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_pwrite error");

// Divergence from posix: lseek(dirfd) will return 0
let r = wasi::fd_seek(dir_fd, 0, wasi::WHENCE_CUR);
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_seek WHENCE_CUR error");
let r = wasi::fd_seek(dir_fd, 0, wasi::WHENCE_SET);
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_seek WHENCE_SET error");
let r = wasi::fd_seek(dir_fd, 0, wasi::WHENCE_END);
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_seek WHENCE_END error");

// Tell isnt in posix, its basically lseek with WHENCE_CUR above
let r = wasi::fd_tell(dir_fd);
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_tell error");

// posix_fadvise(dirfd, 0, 0, POSIX_FADV_DONTNEED) will return 0 on linux.
// not available on mac os.
let r = wasi::fd_advise(dir_fd, 0, 0, wasi::ADVICE_DONTNEED);
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_advise error");

// fallocate(dirfd, FALLOC_FL_ZERO_RANGE, 0, 1) will fail with errno EBADF on linux.
// not available on mac os.
let r = wasi::fd_allocate(dir_fd, 0, 0);
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_allocate error");

// fdatasync(dirfd) will return 0 on linux.
// not available on mac os.
let r = wasi::fd_datasync(dir_fd);
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_datasync error");

// fsync(dirfd) will return 0 on linux.
// not available on mac os.
let r = wasi::fd_sync(dir_fd);
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_sync error");

// fcntl(dirfd, F_SETFL, O_NONBLOCK) will return 0 on linux.
// not available on mac os.
let r = wasi::fd_fdstat_set_flags(dir_fd, wasi::FDFLAGS_NONBLOCK);
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_fdstat_set_flags error");

// ftruncate(dirfd, 1) will fail with errno EINVAL on posix.
// here, we fail with EBADF instead:
let r = wasi::fd_filestat_set_size(dir_fd, 0);
assert_eq!(r, Err(wasi::ERRNO_BADF), "fd_filestat_set_size error");
}

fn main() {
let mut args = env::args();
let prog = args.next().unwrap();
let arg = if let Some(arg) = args.next() {
arg
} else {
eprintln!("usage: {} <scratch directory>", prog);
process::exit(1);
};

// Open scratch directory
let dir_fd = match open_scratch_directory(&arg) {
Ok(dir_fd) => dir_fd,
Err(err) => {
eprintln!("{}", err);
process::exit(1)
}
};

unsafe {
test_fd_dir_ops(dir_fd);
}
}

0 comments on commit d1d381e

Please sign in to comment.