Skip to content

Commit 91ea203

Browse files
committed
corrected set_time behaviour
1 parent 2c96582 commit 91ea203

File tree

3 files changed

+264
-4
lines changed

3 files changed

+264
-4
lines changed

src/lib.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,8 +1377,15 @@ pub extern "C" fn __ic_custom_path_filestat_set_times(
13771377
let fd_stat = FdStat::default();
13781378

13791379
let fst_flags = fst_flags as wasi::Fstflags;
1380-
let mut atim = atim as u64;
1381-
let mut mtim = mtim as u64;
1380+
1381+
let atim = atim as u64;
1382+
let mtim = mtim as u64;
1383+
1384+
if ((fst_flags & wasi::FSTFLAGS_ATIM_NOW) > 0 && (fst_flags & wasi::FSTFLAGS_ATIM) > 0)
1385+
|| ((fst_flags & wasi::FSTFLAGS_MTIM_NOW) > 0 && (fst_flags & wasi::FSTFLAGS_MTIM) > 0)
1386+
{
1387+
return into_errno(stable_fs::error::Error::InvalidArgument);
1388+
}
13821389

13831390
let open_flags = OpenFlags::empty();
13841391

@@ -1393,11 +1400,11 @@ pub extern "C" fn __ic_custom_path_filestat_set_times(
13931400
let now = ic_time();
13941401

13951402
if fst_flags & wasi::FSTFLAGS_ATIM_NOW > 0 {
1396-
atim = now;
1403+
metadata.times.accessed = now;
13971404
}
13981405

13991406
if fst_flags & wasi::FSTFLAGS_MTIM_NOW > 0 {
1400-
mtim = now;
1407+
metadata.times.modified = now;
14011408
}
14021409

14031410
if fst_flags & wasi::FSTFLAGS_ATIM > 0 {

src/test/lib_tests.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,3 +1160,125 @@ fn test_fd_fdstat_set_flags() {
11601160
wasi::path_unlink_file(dir_fd, FILE_NAME).expect("unlinking file");
11611161
}
11621162
}
1163+
1164+
#[test]
1165+
fn test_overwrite_preopen() {
1166+
init(&[], &[]);
1167+
1168+
let root_fd = 3;
1169+
1170+
unsafe {
1171+
let file_fd = create_test_file(3, "test/file.txt");
1172+
wasi::fd_close(file_fd).unwrap();
1173+
1174+
let dir_fd = wasi::path_open(root_fd, 0, "test", wasi::OFLAGS_DIRECTORY, 0, 0, 0).unwrap();
1175+
1176+
let pre_fd: wasi::Fd = (libc::STDERR_FILENO + 1) as wasi::Fd;
1177+
1178+
assert!(dir_fd > pre_fd, "dir_fd number");
1179+
1180+
let old_dir_filestat = wasi::fd_filestat_get(dir_fd).expect("failed fd_filestat_get");
1181+
1182+
// Try to renumber over a preopened directory handle.
1183+
wasi::fd_renumber(dir_fd, pre_fd).expect("renumbering over a preopened file descriptor");
1184+
1185+
// Ensure that pre_fd is still open.
1186+
let new_dir_filestat = wasi::fd_filestat_get(pre_fd).expect("failed fd_filestat_get");
1187+
1188+
// Ensure that we renumbered.
1189+
assert_eq!(old_dir_filestat.dev, new_dir_filestat.dev);
1190+
assert_eq!(old_dir_filestat.ino, new_dir_filestat.ino);
1191+
1192+
// Ensure that dir_fd is closed.
1193+
assert_eq!(
1194+
wasi::fd_fdstat_get(dir_fd).expect_err("failed fd_fdstat_get"),
1195+
wasi::ERRNO_BADF
1196+
);
1197+
}
1198+
}
1199+
1200+
#[test]
1201+
fn test_renumber() {
1202+
init(&[], &[]);
1203+
1204+
let root_fd = 3;
1205+
1206+
unsafe {
1207+
let file_fd = create_test_file(3, "test/file.txt");
1208+
wasi::fd_close(file_fd).unwrap();
1209+
1210+
let dir_fd = wasi::path_open(root_fd, 0, "test", wasi::OFLAGS_DIRECTORY, 0, 0, 0).unwrap();
1211+
1212+
let pre_fd: wasi::Fd = (libc::STDERR_FILENO + 1) as wasi::Fd;
1213+
1214+
assert!(dir_fd > pre_fd, "dir_fd number");
1215+
1216+
// Create a file in the scratch directory.
1217+
let fd_from = wasi::path_open(
1218+
dir_fd,
1219+
0,
1220+
"file1",
1221+
wasi::OFLAGS_CREAT,
1222+
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
1223+
0,
1224+
0,
1225+
)
1226+
.expect("opening a file");
1227+
1228+
assert!(
1229+
fd_from > libc::STDERR_FILENO as wasi::Fd,
1230+
"file descriptor range check",
1231+
);
1232+
1233+
// Get fd_from fdstat attributes
1234+
let fdstat_from =
1235+
wasi::fd_fdstat_get(fd_from).expect("calling fd_fdstat on the open file descriptor");
1236+
1237+
// Create another file in the scratch directory.
1238+
let fd_to = wasi::path_open(
1239+
dir_fd,
1240+
0,
1241+
"file2",
1242+
wasi::OFLAGS_CREAT,
1243+
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
1244+
0,
1245+
0,
1246+
)
1247+
.expect("opening a file");
1248+
assert!(
1249+
fd_to > libc::STDERR_FILENO as wasi::Fd,
1250+
"file descriptor range check",
1251+
);
1252+
1253+
// Renumber fd of file1 into fd of file2
1254+
wasi::fd_renumber(fd_from, fd_to).expect("renumbering two descriptors");
1255+
1256+
// Ensure that fd_from is closed
1257+
assert_eq!(
1258+
wasi::fd_close(fd_from).expect_err("closing already closed file descriptor"),
1259+
wasi::ERRNO_BADF
1260+
);
1261+
1262+
// Ensure that fd_to is still open.
1263+
let fdstat_to =
1264+
wasi::fd_fdstat_get(fd_to).expect("calling fd_fdstat on the open file descriptor");
1265+
assert_eq!(
1266+
fdstat_from.fs_filetype, fdstat_to.fs_filetype,
1267+
"expected fd_to have the same fdstat as fd_from"
1268+
);
1269+
assert_eq!(
1270+
fdstat_from.fs_flags, fdstat_to.fs_flags,
1271+
"expected fd_to have the same fdstat as fd_from"
1272+
);
1273+
assert_eq!(
1274+
fdstat_from.fs_rights_base, fdstat_to.fs_rights_base,
1275+
"expected fd_to have the same fdstat as fd_from"
1276+
);
1277+
assert_eq!(
1278+
fdstat_from.fs_rights_inheriting, fdstat_to.fs_rights_inheriting,
1279+
"expected fd_to have the same fdstat as fd_from"
1280+
);
1281+
1282+
wasi::fd_close(fd_to).expect("closing a file");
1283+
}
1284+
}

src/test/path_tests.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::test::common::{create_test_file, libc};
2+
use crate::wasi_mock::{Clockid, CLOCKID_MONOTONIC};
23
use crate::{init, wasi};
34

45
#[test]
@@ -95,3 +96,133 @@ fn test_interesting_paths() {
9596
.expect("remove_directory on a directory should succeed");
9697
}
9798
}
99+
100+
#[test]
101+
fn test_path_exists() {
102+
init(&[], &[]);
103+
104+
let dir_fd = 3;
105+
106+
unsafe {
107+
// Create a temporary directory
108+
wasi::path_create_directory(dir_fd, "subdir").expect("create directory");
109+
110+
// Check directory exists:
111+
let file_stat = wasi::path_filestat_get(dir_fd, 0, "subdir").expect("reading file stats");
112+
assert_eq!(file_stat.filetype, wasi::FILETYPE_DIRECTORY);
113+
114+
// Should still exist with symlink follow flag:
115+
let file_stat = wasi::path_filestat_get(dir_fd, wasi::LOOKUPFLAGS_SYMLINK_FOLLOW, "subdir")
116+
.expect("reading file stats");
117+
assert_eq!(file_stat.filetype, wasi::FILETYPE_DIRECTORY);
118+
119+
// Create a file:
120+
let fd = create_test_file(dir_fd, "subdir/file");
121+
wasi::fd_close(fd).unwrap();
122+
123+
// Check directory exists:
124+
let file_stat =
125+
wasi::path_filestat_get(dir_fd, 0, "subdir/file").expect("reading file stats");
126+
assert_eq!(file_stat.filetype, wasi::FILETYPE_REGULAR_FILE);
127+
128+
// Should still exist with symlink follow flag:
129+
let file_stat =
130+
wasi::path_filestat_get(dir_fd, wasi::LOOKUPFLAGS_SYMLINK_FOLLOW, "subdir/file")
131+
.expect("reading file stats");
132+
assert_eq!(file_stat.filetype, wasi::FILETYPE_REGULAR_FILE);
133+
134+
wasi::path_unlink_file(dir_fd, "subdir/file").expect("clean up");
135+
wasi::path_remove_directory(dir_fd, "subdir").expect("clean up");
136+
}
137+
}
138+
139+
#[test]
140+
fn test_path_filestat() {
141+
init(&[], &[]);
142+
143+
let dir_fd = 3;
144+
145+
unsafe {
146+
let precission = wasi::clock_res_get(CLOCKID_MONOTONIC).unwrap();
147+
148+
let fdflags = wasi::FDFLAGS_APPEND;
149+
150+
// Create a file in the scratch directory.
151+
let file_fd = wasi::path_open(
152+
dir_fd,
153+
0,
154+
"file",
155+
wasi::OFLAGS_CREAT,
156+
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
157+
0,
158+
// Pass some flags for later retrieval
159+
fdflags,
160+
)
161+
.expect("opening a file");
162+
163+
assert!(
164+
file_fd > libc::STDERR_FILENO as wasi::Fd,
165+
"file descriptor range check",
166+
);
167+
168+
let fdstat = wasi::fd_fdstat_get(file_fd).expect("fd_fdstat_get");
169+
assert_eq!(
170+
fdstat.fs_flags & wasi::FDFLAGS_APPEND,
171+
wasi::FDFLAGS_APPEND,
172+
"file should have the APPEND fdflag used to create the file"
173+
);
174+
175+
// Check file size
176+
let file_stat = wasi::path_filestat_get(dir_fd, 0, "file").expect("reading file stats");
177+
assert_eq!(file_stat.size, 0, "file size should be 0");
178+
179+
// Check path_filestat_set_times
180+
let new_mtim = file_stat.mtim - 2 * precission;
181+
wasi::path_filestat_set_times(dir_fd, 0, "file", 0, new_mtim as u64, wasi::FSTFLAGS_MTIM)
182+
.expect("path_filestat_set_times should succeed");
183+
184+
let modified_file_stat = wasi::path_filestat_get(dir_fd, 0, "file")
185+
.expect("reading file stats after path_filestat_set_times");
186+
187+
assert_eq!(modified_file_stat.mtim, new_mtim, "mtim should change");
188+
189+
assert_eq!(
190+
wasi::path_filestat_set_times(
191+
dir_fd,
192+
0,
193+
"file",
194+
0,
195+
new_mtim as u64,
196+
wasi::FSTFLAGS_MTIM | wasi::FSTFLAGS_MTIM_NOW,
197+
)
198+
.expect_err("MTIM and MTIM_NOW can't both be set"),
199+
wasi::ERRNO_INVAL
200+
);
201+
202+
// check if the times were untouched
203+
let unmodified_file_stat = wasi::path_filestat_get(dir_fd, 0, "file")
204+
.expect("reading file stats after ERRNO_INVAL fd_filestat_set_times");
205+
206+
assert_eq!(
207+
unmodified_file_stat.mtim, new_mtim,
208+
"mtim should not change"
209+
);
210+
211+
// Invalid arguments to set_times:
212+
assert_eq!(
213+
wasi::path_filestat_set_times(
214+
dir_fd,
215+
0,
216+
"file",
217+
0,
218+
0,
219+
wasi::FSTFLAGS_ATIM | wasi::FSTFLAGS_ATIM_NOW,
220+
)
221+
.expect_err("ATIM & ATIM_NOW can't both be set"),
222+
wasi::ERRNO_INVAL
223+
);
224+
225+
wasi::fd_close(file_fd).expect("closing a file");
226+
wasi::path_unlink_file(dir_fd, "file").expect("removing a file");
227+
}
228+
}

0 commit comments

Comments
 (0)