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