1 #![expect(unsafe_op_in_unsafe_fn, reason = "old code, not worth updating yet")]
2 
3 const FIRST_PREOPEN: u32 = 3;
4 
5 unsafe fn path_open_preopen() {
6     let prestat = wasip1::fd_prestat_get(FIRST_PREOPEN).expect("fd 3 is a preopen");
7     assert_eq!(
8         prestat.tag,
9         wasip1::PREOPENTYPE_DIR.raw(),
10         "prestat is a directory"
11     );
12     let mut dst = Vec::with_capacity(prestat.u.dir.pr_name_len);
13     wasip1::fd_prestat_dir_name(FIRST_PREOPEN, dst.as_mut_ptr(), dst.capacity())
14         .expect("get preopen dir name");
15     dst.set_len(prestat.u.dir.pr_name_len);
16 
17     let fdstat = wasip1::fd_fdstat_get(FIRST_PREOPEN).expect("get fdstat");
18 
19     println!(
20         "preopen dir: {:?} base {:?} inheriting {:?}",
21         String::from_utf8_lossy(&dst),
22         fdstat.fs_rights_base,
23         fdstat.fs_rights_inheriting
24     );
25     for (right, name) in directory_base_rights() {
26         assert!(
27             (fdstat.fs_rights_base & right) == right,
28             "fs_rights_base does not have required right `{name}`"
29         );
30     }
31     for (right, name) in directory_inheriting_rights() {
32         assert!(
33             (fdstat.fs_rights_inheriting & right) == right,
34             "fs_rights_inheriting does not have required right `{name}`"
35         );
36     }
37 
38     // Open with same rights it has now:
39     let _ = wasip1::path_open(
40         FIRST_PREOPEN,
41         0,
42         ".",
43         0,
44         fdstat.fs_rights_base,
45         fdstat.fs_rights_inheriting,
46         0,
47     )
48     .expect("open with same rights");
49 
50     // Open with an empty set of rights:
51     let _ = wasip1::path_open(FIRST_PREOPEN, 0, ".", 0, 0, 0, 0).expect("open with empty rights");
52 
53     // Open OFLAGS_DIRECTORY with an empty set of rights:
54     let _ = wasip1::path_open(FIRST_PREOPEN, 0, ".", wasip1::OFLAGS_DIRECTORY, 0, 0, 0)
55         .expect("open with O_DIRECTORY empty rights");
56 
57     // Open OFLAGS_DIRECTORY with just the read right:
58     let _ = wasip1::path_open(
59         FIRST_PREOPEN,
60         0,
61         ".",
62         wasip1::OFLAGS_DIRECTORY,
63         wasip1::RIGHTS_FD_READ,
64         0,
65         0,
66     )
67     .expect("open with O_DIRECTORY and read right");
68 
69     // Open OFLAGS_DIRECTORY and read/write rights should fail with isdir:
70     let err = wasip1::path_open(
71         FIRST_PREOPEN,
72         0,
73         ".",
74         wasip1::OFLAGS_DIRECTORY,
75         wasip1::RIGHTS_FD_READ | wasip1::RIGHTS_FD_WRITE,
76         0,
77         0,
78     )
79     .err()
80     .expect("open with O_DIRECTORY and read/write should fail");
81     assert_eq!(
82         err,
83         wasip1::ERRNO_ISDIR,
84         "opening directory read/write should fail with ISDIR"
85     );
86 }
87 
88 fn main() {
89     unsafe {
90         path_open_preopen();
91     }
92 }
93 
94 // Hard-code the set of rights expected for a preopened directory. This is
95 // more brittle than we wanted to test for, but various userland
96 // implementations expect (at least) this set of rights to be present on all
97 // directories:
98 
99 fn directory_base_rights() -> Vec<(wasip1::Rights, &'static str)> {
100     vec![
101         (
102             wasip1::RIGHTS_PATH_CREATE_DIRECTORY,
103             "PATH_CREATE_DIRECTORY",
104         ),
105         (wasip1::RIGHTS_PATH_CREATE_FILE, "PATH_CREATE_FILE"),
106         (wasip1::RIGHTS_PATH_LINK_SOURCE, "PATH_LINK_SOURCE"),
107         (wasip1::RIGHTS_PATH_LINK_TARGET, "PATH_LINK_TARGET"),
108         (wasip1::RIGHTS_PATH_OPEN, "PATH_OPEN"),
109         (wasip1::RIGHTS_FD_READDIR, "FD_READDIR"),
110         (wasip1::RIGHTS_PATH_READLINK, "PATH_READLINK"),
111         (wasip1::RIGHTS_PATH_RENAME_SOURCE, "PATH_RENAME_SOURCE"),
112         (wasip1::RIGHTS_PATH_RENAME_TARGET, "PATH_RENAME_TARGET"),
113         (wasip1::RIGHTS_PATH_SYMLINK, "PATH_SYMLINK"),
114         (
115             wasip1::RIGHTS_PATH_REMOVE_DIRECTORY,
116             "PATH_REMOVE_DIRECTORY",
117         ),
118         (wasip1::RIGHTS_PATH_UNLINK_FILE, "PATH_UNLINK_FILE"),
119         (wasip1::RIGHTS_PATH_FILESTAT_GET, "PATH_FILESTAT_GET"),
120         (
121             wasip1::RIGHTS_PATH_FILESTAT_SET_TIMES,
122             "PATH_FILESTAT_SET_TIMES",
123         ),
124         (wasip1::RIGHTS_FD_FILESTAT_GET, "FD_FILESTAT_GET"),
125         (
126             wasip1::RIGHTS_FD_FILESTAT_SET_TIMES,
127             "FD_FILESTAT_SET_TIMES",
128         ),
129     ]
130 }
131 
132 pub(crate) fn directory_inheriting_rights() -> Vec<(wasip1::Rights, &'static str)> {
133     let mut rights = directory_base_rights();
134     rights.extend_from_slice(&[
135         (wasip1::RIGHTS_FD_DATASYNC, "FD_DATASYNC"),
136         (wasip1::RIGHTS_FD_READ, "FD_READ"),
137         (wasip1::RIGHTS_FD_SEEK, "FD_SEEK"),
138         (wasip1::RIGHTS_FD_FDSTAT_SET_FLAGS, "FD_FDSTAT_SET_FLAGS"),
139         (wasip1::RIGHTS_FD_SYNC, "FD_SYNC"),
140         (wasip1::RIGHTS_FD_TELL, "FD_TELL"),
141         (wasip1::RIGHTS_FD_WRITE, "FD_WRITE"),
142         (wasip1::RIGHTS_FD_ADVISE, "FD_ADVISE"),
143         (wasip1::RIGHTS_FD_ALLOCATE, "FD_ALLOCATE"),
144         (wasip1::RIGHTS_FD_FILESTAT_GET, "FD_FILESTAT_GET"),
145         (wasip1::RIGHTS_FD_FILESTAT_SET_SIZE, "FD_FILESTAT_SET_SIZE"),
146         (
147             wasip1::RIGHTS_FD_FILESTAT_SET_TIMES,
148             "FD_FILESTAT_SET_TIMES",
149         ),
150         (wasip1::RIGHTS_POLL_FD_READWRITE, "POLL_FD_READWRITE"),
151     ]);
152     rights
153 }
154