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 
test_interesting_paths(dir_fd: wasip1::Fd, arg: &str)6 unsafe fn test_interesting_paths(dir_fd: wasip1::Fd, arg: &str) {
7     // Create a directory in the scratch directory.
8     wasip1::path_create_directory(dir_fd, "dir").expect("creating dir");
9 
10     // Create a directory in the directory we just created.
11     wasip1::path_create_directory(dir_fd, "dir/nested").expect("creating a nested dir");
12 
13     // Create a file in the nested directory.
14     create_file(dir_fd, "dir/nested/file");
15 
16     // Now open it with an absolute path.
17     assert_errno!(
18         wasip1::path_open(dir_fd, 0, "/dir/nested/file", 0, 0, 0, 0)
19             .expect_err("opening a file with an absolute path"),
20         wasip1::ERRNO_PERM
21     );
22 
23     // Now open it with a path containing "..".
24     let mut file_fd = wasip1::path_open(
25         dir_fd,
26         0,
27         "dir/.//nested/../../dir/nested/../nested///./file",
28         0,
29         0,
30         0,
31         0,
32     )
33     .expect("opening a file with \"..\" in the path");
34     assert!(
35         file_fd > libc::STDERR_FILENO as wasip1::Fd,
36         "file descriptor range check",
37     );
38     wasip1::fd_close(file_fd).expect("closing a file");
39 
40     // Now open it with a trailing NUL. Windows will allow this.
41     assert_errno!(
42         wasip1::path_open(dir_fd, 0, "dir/nested/file\0", 0, 0, 0, 0)
43             .expect_err("opening a file with a trailing NUL"),
44         unix => wasip1::ERRNO_INVAL,
45         windows => wasip1::ERRNO_NOENT
46     );
47 
48     // Now open it with a trailing slash.
49     assert_errno!(
50         wasip1::path_open(dir_fd, 0, "dir/nested/file/", 0, 0, 0, 0)
51             .expect_err("opening a file with a trailing slash should fail"),
52         wasip1::ERRNO_NOTDIR,
53         wasip1::ERRNO_NOENT
54     );
55 
56     // Now open it with trailing slashes.
57     assert_errno!(
58         wasip1::path_open(dir_fd, 0, "dir/nested/file///", 0, 0, 0, 0)
59             .expect_err("opening a file with trailing slashes should fail"),
60         wasip1::ERRNO_NOTDIR,
61         wasip1::ERRNO_NOENT
62     );
63 
64     // Now open the directory with a trailing slash.
65     file_fd = wasip1::path_open(dir_fd, 0, "dir/nested/", 0, 0, 0, 0)
66         .expect("opening a directory with a trailing slash");
67     assert!(
68         file_fd > libc::STDERR_FILENO as wasip1::Fd,
69         "file descriptor range check",
70     );
71     wasip1::fd_close(file_fd).expect("closing a file");
72 
73     // Now open the directory with trailing slashes.
74     file_fd = wasip1::path_open(dir_fd, 0, "dir/nested///", 0, 0, 0, 0)
75         .expect("opening a directory with trailing slashes");
76     assert!(
77         file_fd > libc::STDERR_FILENO as wasip1::Fd,
78         "file descriptor range check",
79     );
80     wasip1::fd_close(file_fd).expect("closing a file");
81 
82     // Now open it with a path containing too many ".."s.
83     let bad_path = format!("dir/nested/../../../{arg}/dir/nested/file");
84     assert_errno!(
85         wasip1::path_open(dir_fd, 0, &bad_path, 0, 0, 0, 0)
86             .expect_err("opening a file with too many \"..\"s in the path should fail"),
87         wasip1::ERRNO_PERM
88     );
89     wasip1::path_unlink_file(dir_fd, "dir/nested/file")
90         .expect("unlink_file on a symlink should succeed");
91     wasip1::path_remove_directory(dir_fd, "dir/nested")
92         .expect("remove_directory on a directory should succeed");
93     wasip1::path_remove_directory(dir_fd, "dir")
94         .expect("remove_directory on a directory should succeed");
95 }
96 
main()97 fn main() {
98     let mut args = env::args();
99     let prog = args.next().unwrap();
100     let arg = if let Some(arg) = args.next() {
101         arg
102     } else {
103         eprintln!("usage: {prog} <scratch directory>");
104         process::exit(1);
105     };
106 
107     // Open scratch directory
108     let dir_fd = match open_scratch_directory(&arg) {
109         Ok(dir_fd) => dir_fd,
110         Err(err) => {
111             eprintln!("{err}");
112             process::exit(1)
113         }
114     };
115 
116     // Run the tests.
117     unsafe { test_interesting_paths(dir_fd, &arg) }
118 }
119