1*b315a0a8SYosh #![expect(unsafe_op_in_unsafe_fn, reason = "old code, not worth updating yet")]
2*b315a0a8SYosh 
3*b315a0a8SYosh use std::{env, process};
4*b315a0a8SYosh use test_programs::preview1::open_scratch_directory;
5*b315a0a8SYosh 
test_file_long_write(dir_fd: wasip1::Fd, filename: &str)6*b315a0a8SYosh unsafe fn test_file_long_write(dir_fd: wasip1::Fd, filename: &str) {
7*b315a0a8SYosh     // Open a file for writing
8*b315a0a8SYosh     let file_fd = wasip1::path_open(
9*b315a0a8SYosh         dir_fd,
10*b315a0a8SYosh         0,
11*b315a0a8SYosh         filename,
12*b315a0a8SYosh         wasip1::OFLAGS_CREAT,
13*b315a0a8SYosh         wasip1::RIGHTS_FD_WRITE,
14*b315a0a8SYosh         0,
15*b315a0a8SYosh         0,
16*b315a0a8SYosh     )
17*b315a0a8SYosh     .expect("creating a file for writing");
18*b315a0a8SYosh 
19*b315a0a8SYosh     let mut content = Vec::new();
20*b315a0a8SYosh     // 16 byte string, 4096 times, is 64k
21*b315a0a8SYosh     for n in 0..4096 {
22*b315a0a8SYosh         let chunk = format!("123456789 {n:05} ");
23*b315a0a8SYosh         assert_eq!(chunk.as_str().as_bytes().len(), 16);
24*b315a0a8SYosh         content.extend_from_slice(chunk.as_str().as_bytes());
25*b315a0a8SYosh     }
26*b315a0a8SYosh 
27*b315a0a8SYosh     // Write to the file
28*b315a0a8SYosh     let nwritten = wasip1::fd_write(
29*b315a0a8SYosh         file_fd,
30*b315a0a8SYosh         &[wasip1::Ciovec {
31*b315a0a8SYosh             buf: content.as_slice().as_ptr() as *const _,
32*b315a0a8SYosh             buf_len: content.len(),
33*b315a0a8SYosh         }],
34*b315a0a8SYosh     )
35*b315a0a8SYosh     .expect("writing file content");
36*b315a0a8SYosh     assert_eq!(nwritten, content.len(), "nwritten bytes check");
37*b315a0a8SYosh 
38*b315a0a8SYosh     let stat = wasip1::fd_filestat_get(file_fd).expect("reading file stats");
39*b315a0a8SYosh     assert_eq!(
40*b315a0a8SYosh         stat.size,
41*b315a0a8SYosh         content.len() as u64,
42*b315a0a8SYosh         "file should be size of content",
43*b315a0a8SYosh     );
44*b315a0a8SYosh 
45*b315a0a8SYosh     wasip1::fd_close(file_fd).expect("closing the file");
46*b315a0a8SYosh     // Open the file for reading
47*b315a0a8SYosh     let file_fd = wasip1::path_open(dir_fd, 0, filename, 0, wasip1::RIGHTS_FD_READ, 0, 0)
48*b315a0a8SYosh         .expect("open the file for reading");
49*b315a0a8SYosh 
50*b315a0a8SYosh     // Read the file's contents
51*b315a0a8SYosh     let buffer = &mut [0u8; 100];
52*b315a0a8SYosh     let nread = wasip1::fd_read(
53*b315a0a8SYosh         file_fd,
54*b315a0a8SYosh         &[wasip1::Iovec {
55*b315a0a8SYosh             buf: buffer.as_mut_ptr(),
56*b315a0a8SYosh             buf_len: buffer.len(),
57*b315a0a8SYosh         }],
58*b315a0a8SYosh     )
59*b315a0a8SYosh     .expect("reading first chunk file content");
60*b315a0a8SYosh 
61*b315a0a8SYosh     assert_eq!(nread, buffer.len(), "read first chunk");
62*b315a0a8SYosh     assert_eq!(
63*b315a0a8SYosh         buffer,
64*b315a0a8SYosh         &content[..buffer.len()],
65*b315a0a8SYosh         "contents of first read chunk"
66*b315a0a8SYosh     );
67*b315a0a8SYosh 
68*b315a0a8SYosh     let end_cursor = content.len() - buffer.len();
69*b315a0a8SYosh     wasip1::fd_seek(file_fd, end_cursor as i64, wasip1::WHENCE_SET)
70*b315a0a8SYosh         .expect("seeking to end of file minus buffer size");
71*b315a0a8SYosh 
72*b315a0a8SYosh     let nread = wasip1::fd_read(
73*b315a0a8SYosh         file_fd,
74*b315a0a8SYosh         &[wasip1::Iovec {
75*b315a0a8SYosh             buf: buffer.as_mut_ptr(),
76*b315a0a8SYosh             buf_len: buffer.len(),
77*b315a0a8SYosh         }],
78*b315a0a8SYosh     )
79*b315a0a8SYosh     .expect("reading end chunk of file content");
80*b315a0a8SYosh 
81*b315a0a8SYosh     assert_eq!(nread, buffer.len(), "read end chunk len");
82*b315a0a8SYosh     assert_eq!(buffer, &content[end_cursor..], "contents of end read chunk");
83*b315a0a8SYosh 
84*b315a0a8SYosh     wasip1::fd_close(file_fd).expect("closing the file");
85*b315a0a8SYosh 
86*b315a0a8SYosh     // Open a file for writing
87*b315a0a8SYosh     let filename = "test-zero-write-fails.txt";
88*b315a0a8SYosh     let file_fd = wasip1::path_open(
89*b315a0a8SYosh         dir_fd,
90*b315a0a8SYosh         0,
91*b315a0a8SYosh         filename,
92*b315a0a8SYosh         wasip1::OFLAGS_CREAT,
93*b315a0a8SYosh         wasip1::RIGHTS_FD_WRITE,
94*b315a0a8SYosh         0,
95*b315a0a8SYosh         0,
96*b315a0a8SYosh     )
97*b315a0a8SYosh     .expect("creating a file for writing");
98*b315a0a8SYosh     wasip1::fd_close(file_fd).expect("closing the file");
99*b315a0a8SYosh     let file_fd = wasip1::path_open(dir_fd, 0, filename, 0, wasip1::RIGHTS_FD_READ, 0, 0)
100*b315a0a8SYosh         .expect("opening a file for writing");
101*b315a0a8SYosh     let res = wasip1::fd_write(
102*b315a0a8SYosh         file_fd,
103*b315a0a8SYosh         &[wasip1::Ciovec {
104*b315a0a8SYosh             buf: 3 as *const u8,
105*b315a0a8SYosh             buf_len: 0,
106*b315a0a8SYosh         }],
107*b315a0a8SYosh     );
108*b315a0a8SYosh     assert!(
109*b315a0a8SYosh         res == Err(wasip1::ERRNO_BADF) || res == Err(wasip1::ERRNO_PERM),
110*b315a0a8SYosh         "bad result {res:?}"
111*b315a0a8SYosh     )
112*b315a0a8SYosh }
113*b315a0a8SYosh 
main()114*b315a0a8SYosh fn main() {
115*b315a0a8SYosh     let mut args = env::args();
116*b315a0a8SYosh     let prog = args.next().unwrap();
117*b315a0a8SYosh     let arg = if let Some(arg) = args.next() {
118*b315a0a8SYosh         arg
119*b315a0a8SYosh     } else {
120*b315a0a8SYosh         eprintln!("usage: {prog} <scratch directory>");
121*b315a0a8SYosh         process::exit(1);
122*b315a0a8SYosh     };
123*b315a0a8SYosh 
124*b315a0a8SYosh     // Open scratch directory
125*b315a0a8SYosh     let dir_fd = match open_scratch_directory(&arg) {
126*b315a0a8SYosh         Ok(dir_fd) => dir_fd,
127*b315a0a8SYosh         Err(err) => {
128*b315a0a8SYosh             eprintln!("{err}");
129*b315a0a8SYosh             process::exit(1)
130*b315a0a8SYosh         }
131*b315a0a8SYosh     };
132*b315a0a8SYosh 
133*b315a0a8SYosh     // Run the tests.
134*b315a0a8SYosh     unsafe { test_file_long_write(dir_fd, "long_write.txt") }
135*b315a0a8SYosh }
136