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 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 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 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