`fd_filestat_set_times` with preopened directory file descriptors
Not sure this is a bug, but I can't find any previous discussion about this particular case.
Calling fd_filestat_set_times with a preopened directory fd returns badf. I'm aware there is a conformance test that assert certain fd_* calls should fail with dir fds, but it's not immediately clear to me why this should be the case for fd_filestat_set_times and preopened directories.
Test Case
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
int main() {
struct timespec times[2];
times[0].tv_nsec = UTIME_NOW;
times[1].tv_nsec = UTIME_NOW;
int ret = futimens(3, times);
if (ret != 0 ) {
perror("futimens");
return 1;
}
return 0;
}
Steps to Reproduce
Compile the snippet with wasi-sdk and run with Wasmtime, preopen a directory.
Expected Results
It should be possible to set times on a directory.
Actual Results
fd_filestat_set_times return badf.
Versions and Environment
Wasmtime version or commit: 4f2d634ca4291a09003eaba26f989cd544c1a289
Operating system: Darwin, Fedora 39
Architecture: amd64
Extra Info
Anything else you'd like to add?
This is probably a result of including O_PATH when preopening directories: https://github.com/bytecodealliance/cap-std/blob/3663202c6de1bc440764282524a21e14b924925d/cap-primitives/src/rustix/fs/dir_utils.rs#L117
EDIT: I just tested. fd_filestat_set_times indeed works if we omit the O_PATH in cap-std.
I can submit a PR for cap-std if folks are OK with this behavior.
Apologies for the delay in getting back to you here. Can you clarify how to reproduce this issue? I checked out the version you listed, compiled the above program with wasi-sdk-21.0, and ran cargo run run --dir . a.out locally. I was unable to reproduce a failure locally at least.
I was able to reproduce the error you're seeing on ubuntu-20.04.
Given that you're attempting to use utime on a dir, should you use utimensat instead of futimens? The purpose of the OFlags::PATH flag in fd_filestat_set_times is to avoid actually opening the file, which I think is the correct behavior here. Here's my modified version of your test program that exits normally for me:
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
int main() {
struct timespec times[2];
times[0].tv_nsec = UTIME_NOW;
times[1].tv_nsec = UTIME_NOW;
int ret = utimensat(3, ".", times, 0);
if (ret != 0 ) {
perror("utimensat");
return 1;
}
return 0;
}
Thinking about this more, my response above only tells you how to avoid the problem, given that preopens are opened with O_PATH. Sorry about that!
I'm going to discuss this more with @sunfishcode, and see if we can come up with a recommendation for how best to proceed.