1 use std::{env, process};
2 use wasi_tests::{create_file, open_scratch_directory};
3
test_truncation_rights(dir_fd: wasi::Fd)4 unsafe fn test_truncation_rights(dir_fd: wasi::Fd) {
5 // Create a file in the scratch directory.
6 create_file(dir_fd, "file");
7
8 // Get the rights for the scratch directory.
9 let mut dir_fdstat =
10 wasi::fd_fdstat_get(dir_fd).expect("calling fd_fdstat on the scratch directory");
11 assert_eq!(
12 dir_fdstat.fs_filetype,
13 wasi::FILETYPE_DIRECTORY,
14 "expected the scratch directory to be a directory",
15 );
16 assert_eq!(
17 dir_fdstat.fs_flags, 0,
18 "expected the scratch directory to have no special flags",
19 );
20 assert_eq!(
21 dir_fdstat.fs_rights_base & wasi::RIGHTS_FD_FILESTAT_SET_SIZE,
22 0,
23 "directories shouldn't have the fd_filestat_set_size right",
24 );
25
26 // If we have the right to set sizes from paths, test that it works.
27 if (dir_fdstat.fs_rights_base & wasi::RIGHTS_PATH_FILESTAT_SET_SIZE) == 0 {
28 eprintln!("implementation doesn't support setting file sizes, skipping");
29 } else {
30 // Test that we can truncate the file.
31 let mut file_fd = wasi::path_open(dir_fd, 0, "file", wasi::OFLAGS_TRUNC, 0, 0, 0)
32 .expect("truncating a file");
33 wasi::fd_close(file_fd).expect("closing a file");
34
35 let mut rights_base: wasi::Rights = dir_fdstat.fs_rights_base;
36 let mut rights_inheriting: wasi::Rights = dir_fdstat.fs_rights_inheriting;
37
38 if (rights_inheriting & wasi::RIGHTS_FD_FILESTAT_SET_SIZE) == 0 {
39 eprintln!("implementation doesn't support setting file sizes through file descriptors, skipping");
40 } else {
41 rights_inheriting &= !wasi::RIGHTS_FD_FILESTAT_SET_SIZE;
42 wasi::fd_fdstat_set_rights(dir_fd, rights_base, rights_inheriting)
43 .expect("droping fd_filestat_set_size inheriting right on a directory");
44 }
45
46 // Test that we can truncate the file without the
47 // wasi_unstable::RIGHT_FD_FILESTAT_SET_SIZE right.
48 file_fd = wasi::path_open(dir_fd, 0, "file", wasi::OFLAGS_TRUNC, 0, 0, 0)
49 .expect("truncating a file without fd_filestat_set_size right");
50 wasi::fd_close(file_fd).expect("closing a file");
51
52 rights_base &= !wasi::RIGHTS_PATH_FILESTAT_SET_SIZE;
53 wasi::fd_fdstat_set_rights(dir_fd, rights_base, rights_inheriting)
54 .expect("droping path_filestat_set_size base right on a directory");
55
56 // Test that clearing wasi_unstable::RIGHT_PATH_FILESTAT_SET_SIZE actually
57 // took effect.
58 dir_fdstat = wasi::fd_fdstat_get(dir_fd).expect("reading the fdstat from a directory");
59 assert_eq!(
60 (dir_fdstat.fs_rights_base & wasi::RIGHTS_PATH_FILESTAT_SET_SIZE),
61 0,
62 "reading the fdstat from a directory",
63 );
64
65 // Test that we can't truncate the file without the
66 // wasi_unstable::RIGHT_PATH_FILESTAT_SET_SIZE right.
67 assert_eq!(
68 wasi::path_open(dir_fd, 0, "file", wasi::OFLAGS_TRUNC, 0, 0, 0)
69 .expect_err("truncating a file without path_filestat_set_size right")
70 .raw_error(),
71 wasi::ERRNO_NOTCAPABLE,
72 "errno should be ERRNO_NOTCAPABLE",
73 );
74 }
75
76 wasi::path_unlink_file(dir_fd, "file").expect("removing a file");
77 }
78
main()79 fn main() {
80 let mut args = env::args();
81 let prog = args.next().unwrap();
82 let arg = if let Some(arg) = args.next() {
83 arg
84 } else {
85 eprintln!("usage: {} <scratch directory>", prog);
86 process::exit(1);
87 };
88
89 // Open scratch directory
90 let dir_fd = match open_scratch_directory(&arg) {
91 Ok(dir_fd) => dir_fd,
92 Err(err) => {
93 eprintln!("{}", err);
94 process::exit(1)
95 }
96 };
97
98 // Run the tests.
99 unsafe { test_truncation_rights(dir_fd) }
100 }
101