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::{create_file, open_scratch_directory};
5 
test_readlink(dir_fd: wasip1::Fd)6 unsafe fn test_readlink(dir_fd: wasip1::Fd) {
7     // Create a file in the scratch directory.
8     create_file(dir_fd, "target");
9 
10     // Create a symlink
11     wasip1::path_symlink("target", dir_fd, "symlink").expect("creating a symlink");
12 
13     // Read link into the buffer
14     let buf = &mut [0u8; 10];
15     let bufused = wasip1::path_readlink(dir_fd, "symlink", buf.as_mut_ptr(), buf.len())
16         .expect("readlink should succeed");
17     assert_eq!(bufused, 6, "should use 6 bytes of the buffer");
18     assert_eq!(&buf[..6], b"target", "buffer should contain 'target'");
19     assert_eq!(
20         &buf[6..],
21         &[0u8; 4],
22         "the remaining bytes should be untouched"
23     );
24 
25     // Read link into smaller buffer than the actual link's length
26     let buf = &mut [0u8; 4];
27     let bufused = wasip1::path_readlink(dir_fd, "symlink", buf.as_mut_ptr(), buf.len())
28         .expect("readlink with too-small buffer should silently truncate");
29     assert_eq!(bufused, 4);
30     assert_eq!(buf, b"targ");
31 
32     // Clean up.
33     wasip1::path_unlink_file(dir_fd, "target").expect("removing a file");
34     wasip1::path_unlink_file(dir_fd, "symlink").expect("removing a file");
35 }
36 
test_incremental_readlink(dir_fd: wasip1::Fd)37 unsafe fn test_incremental_readlink(dir_fd: wasip1::Fd) {
38     let filename = "Действие";
39     create_file(dir_fd, filename);
40 
41     wasip1::path_symlink(filename, dir_fd, "symlink").expect("creating a symlink");
42 
43     let mut buf = Vec::new();
44     loop {
45         if buf.capacity() > 2 * filename.len() {
46             panic!()
47         }
48         let bufused = wasip1::path_readlink(dir_fd, "symlink", buf.as_mut_ptr(), buf.capacity())
49             .expect("readlink should succeed");
50         buf.set_len(bufused);
51         if buf.capacity() > filename.len() {
52             assert!(buf.starts_with(filename.as_bytes()));
53             break;
54         }
55         buf = Vec::with_capacity(buf.capacity() + 1);
56     }
57     wasip1::path_unlink_file(dir_fd, filename).expect("removing a file");
58     wasip1::path_unlink_file(dir_fd, "symlink").expect("removing a file");
59 }
60 
main()61 fn main() {
62     let mut args = env::args();
63     let prog = args.next().unwrap();
64     let arg = if let Some(arg) = args.next() {
65         arg
66     } else {
67         eprintln!("usage: {prog} <scratch directory>");
68         process::exit(1);
69     };
70 
71     // Open scratch directory
72     let dir_fd = match open_scratch_directory(&arg) {
73         Ok(dir_fd) => dir_fd,
74         Err(err) => {
75             eprintln!("{err}");
76             process::exit(1)
77         }
78     };
79 
80     // Run the tests.
81     unsafe { test_readlink(dir_fd) }
82     unsafe { test_incremental_readlink(dir_fd) }
83 }
84