1 #![expect(unsafe_op_in_unsafe_fn, reason = "old code, not worth updating yet")]
2 
3 use std::{env, process};
4 use test_programs::preview1::{assert_errno, create_file, open_scratch_directory};
5 
6 unsafe fn test_path_open_read_write(dir_fd: wasip1::Fd) {
7     create_file(dir_fd, "file");
8 
9     let f_readonly = wasip1::path_open(dir_fd, 0, "file", 0, wasip1::RIGHTS_FD_READ, 0, 0)
10         .expect("open file readonly");
11 
12     let stat = wasip1::fd_fdstat_get(f_readonly).expect("get fdstat readonly");
13     assert!(
14         stat.fs_rights_base & wasip1::RIGHTS_FD_READ == wasip1::RIGHTS_FD_READ,
15         "readonly has read right"
16     );
17     assert!(
18         stat.fs_rights_base & wasip1::RIGHTS_FD_WRITE == 0,
19         "readonly does not have write right"
20     );
21 
22     let buffer = &mut [0u8; 100];
23     let iovec = wasip1::Iovec {
24         buf: buffer.as_mut_ptr(),
25         buf_len: buffer.len(),
26     };
27     let nread = wasip1::fd_read(f_readonly, &[iovec]).expect("reading readonly file");
28     assert_eq!(nread, 0, "readonly file is empty");
29 
30     let write_buffer = &[1u8; 50];
31     let ciovec = wasip1::Ciovec {
32         buf: write_buffer.as_ptr(),
33         buf_len: write_buffer.len(),
34     };
35     // PERM is only the failure on windows under wasmtime-wasi. wasi-common
36     // fails on windows with BADF, so we can't use the `windows =>` syntax
37     // because that doesn't support alternatives like the agnostic syntax does.
38     assert_errno!(
39         wasip1::fd_write(f_readonly, &[ciovec])
40             .err()
41             .expect("read of writeonly fails"),
42         wasip1::ERRNO_PERM,
43         wasip1::ERRNO_BADF
44     );
45 
46     wasip1::fd_close(f_readonly).expect("close readonly");
47 
48     // =============== WRITE ONLY ==================
49     let f_writeonly = wasip1::path_open(dir_fd, 0, "file", 0, wasip1::RIGHTS_FD_WRITE, 0, 0)
50         .expect("open file writeonly");
51 
52     let stat = wasip1::fd_fdstat_get(f_writeonly).expect("get fdstat writeonly");
53     assert!(
54         stat.fs_rights_base & wasip1::RIGHTS_FD_READ == 0,
55         "writeonly does not have read right"
56     );
57     assert!(
58         stat.fs_rights_base & wasip1::RIGHTS_FD_READDIR == 0,
59         "writeonly does not have readdir right"
60     );
61     assert!(
62         stat.fs_rights_base & wasip1::RIGHTS_FD_WRITE == wasip1::RIGHTS_FD_WRITE,
63         "writeonly has write right"
64     );
65 
66     // See above for description of PERM
67     assert_errno!(
68         wasip1::fd_read(f_writeonly, &[iovec])
69             .err()
70             .expect("read of writeonly fails"),
71         wasip1::ERRNO_PERM,
72         wasip1::ERRNO_BADF
73     );
74     let bytes_written = wasip1::fd_write(f_writeonly, &[ciovec]).expect("write to writeonly");
75     assert_eq!(bytes_written, write_buffer.len());
76 
77     wasip1::fd_close(f_writeonly).expect("close writeonly");
78 
79     // ============== READ WRITE =======================
80 
81     let f_readwrite = wasip1::path_open(
82         dir_fd,
83         0,
84         "file",
85         0,
86         wasip1::RIGHTS_FD_READ | wasip1::RIGHTS_FD_WRITE,
87         0,
88         0,
89     )
90     .expect("open file readwrite");
91     let stat = wasip1::fd_fdstat_get(f_readwrite).expect("get fdstat readwrite");
92     assert!(
93         stat.fs_rights_base & wasip1::RIGHTS_FD_READ == wasip1::RIGHTS_FD_READ,
94         "readwrite has read right"
95     );
96     assert!(
97         stat.fs_rights_base & wasip1::RIGHTS_FD_WRITE == wasip1::RIGHTS_FD_WRITE,
98         "readwrite has write right"
99     );
100 
101     let nread = wasip1::fd_read(f_readwrite, &[iovec]).expect("reading readwrite file");
102     assert_eq!(
103         nread,
104         write_buffer.len(),
105         "readwrite file contains contents from writeonly open"
106     );
107 
108     let write_buffer_2 = &[2u8; 25];
109     let ciovec = wasip1::Ciovec {
110         buf: write_buffer_2.as_ptr(),
111         buf_len: write_buffer_2.len(),
112     };
113     let bytes_written = wasip1::fd_write(f_readwrite, &[ciovec]).expect("write to readwrite");
114     assert_eq!(bytes_written, write_buffer_2.len());
115 
116     let filestat = wasip1::fd_filestat_get(f_readwrite).expect("get filestat readwrite");
117     assert_eq!(
118         filestat.size as usize,
119         write_buffer.len() + write_buffer_2.len(),
120         "total written is both write buffers"
121     );
122 
123     wasip1::fd_close(f_readwrite).expect("close readwrite");
124 
125     wasip1::path_unlink_file(dir_fd, "file").expect("removing a file");
126 }
127 
128 fn main() {
129     let mut args = env::args();
130     let prog = args.next().unwrap();
131     let arg = if let Some(arg) = args.next() {
132         arg
133     } else {
134         eprintln!("usage: {prog} <scratch directory>");
135         process::exit(1);
136     };
137 
138     // Open scratch directory
139     let dir_fd = match open_scratch_directory(&arg) {
140         Ok(dir_fd) => dir_fd,
141         Err(err) => {
142             eprintln!("{err}");
143             process::exit(1)
144         }
145     };
146 
147     // Run the tests.
148     unsafe { test_path_open_read_write(dir_fd) }
149 }
150