1 #![expect(unsafe_op_in_unsafe_fn, reason = "old code, not worth updating yet")]
2 
3 use std::{env, process, time::Duration};
4 use test_programs::preview1::{
5     TestConfig, assert_errno, assert_fs_time_eq, open_scratch_directory,
6 };
7 
test_path_filestat(dir_fd: wasip1::Fd)8 unsafe fn test_path_filestat(dir_fd: wasip1::Fd) {
9     let cfg = TestConfig::from_env();
10     let fdflags = wasip1::FDFLAGS_APPEND;
11 
12     // Create a file in the scratch directory.
13     let file_fd = wasip1::path_open(
14         dir_fd,
15         0,
16         "file",
17         wasip1::OFLAGS_CREAT,
18         wasip1::RIGHTS_FD_READ | wasip1::RIGHTS_FD_WRITE,
19         0,
20         // Pass some flags for later retrieval
21         fdflags,
22     )
23     .expect("opening a file");
24     assert!(
25         file_fd > libc::STDERR_FILENO as wasip1::Fd,
26         "file descriptor range check",
27     );
28 
29     let fdstat = wasip1::fd_fdstat_get(file_fd).expect("fd_fdstat_get");
30     assert_eq!(
31         fdstat.fs_flags & wasip1::FDFLAGS_APPEND,
32         wasip1::FDFLAGS_APPEND,
33         "file should have the APPEND fdflag used to create the file"
34     );
35     assert_errno!(
36         wasip1::path_open(
37             dir_fd,
38             0,
39             "file",
40             0,
41             wasip1::RIGHTS_FD_READ | wasip1::RIGHTS_FD_WRITE,
42             0,
43             wasip1::FDFLAGS_SYNC,
44         )
45         .expect_err("FDFLAGS_SYNC not supported by platform"),
46         wasip1::ERRNO_NOTSUP
47     );
48 
49     // Check file size
50     let file_stat = wasip1::path_filestat_get(dir_fd, 0, "file").expect("reading file stats");
51     assert_eq!(file_stat.size, 0, "file size should be 0");
52 
53     // Check path_filestat_set_times
54     let new_mtim = Duration::from_nanos(file_stat.mtim) - 2 * cfg.fs_time_precision();
55     wasip1::path_filestat_set_times(
56         dir_fd,
57         0,
58         "file",
59         0,
60         new_mtim.as_nanos() as u64,
61         wasip1::FSTFLAGS_MTIM,
62     )
63     .expect("path_filestat_set_times should succeed");
64 
65     let modified_file_stat = wasip1::path_filestat_get(dir_fd, 0, "file")
66         .expect("reading file stats after path_filestat_set_times");
67 
68     assert_fs_time_eq!(
69         Duration::from_nanos(modified_file_stat.mtim),
70         new_mtim,
71         "mtim should change"
72     );
73 
74     assert_errno!(
75         wasip1::path_filestat_set_times(
76             dir_fd,
77             0,
78             "file",
79             0,
80             new_mtim.as_nanos() as u64,
81             wasip1::FSTFLAGS_MTIM | wasip1::FSTFLAGS_MTIM_NOW,
82         )
83         .expect_err("MTIM and MTIM_NOW can't both be set"),
84         wasip1::ERRNO_INVAL
85     );
86 
87     // check if the times were untouched
88     let unmodified_file_stat = wasip1::path_filestat_get(dir_fd, 0, "file")
89         .expect("reading file stats after ERRNO_INVAL fd_filestat_set_times");
90 
91     assert_fs_time_eq!(
92         Duration::from_nanos(unmodified_file_stat.mtim),
93         new_mtim,
94         "mtim should not change"
95     );
96 
97     // Invalid arguments to set_times:
98     assert_errno!(
99         wasip1::path_filestat_set_times(
100             dir_fd,
101             0,
102             "file",
103             0,
104             0,
105             wasip1::FSTFLAGS_ATIM | wasip1::FSTFLAGS_ATIM_NOW,
106         )
107         .expect_err("ATIM & ATIM_NOW can't both be set"),
108         wasip1::ERRNO_INVAL
109     );
110 
111     wasip1::fd_close(file_fd).expect("closing a file");
112     wasip1::path_unlink_file(dir_fd, "file").expect("removing a file");
113 }
main()114 fn main() {
115     let mut args = env::args();
116     let prog = args.next().unwrap();
117     let arg = if let Some(arg) = args.next() {
118         arg
119     } else {
120         eprintln!("usage: {prog} <scratch directory>");
121         process::exit(1);
122     };
123 
124     // Open scratch directory
125     let dir_fd = match open_scratch_directory(&arg) {
126         Ok(dir_fd) => dir_fd,
127         Err(err) => {
128             eprintln!("{err}");
129             process::exit(1)
130         }
131     };
132 
133     // Run the tests.
134     unsafe { test_path_filestat(dir_fd) }
135 }
136