diff --git a/Userland/Libraries/LibWasm/WASI/Wasi.cpp b/Userland/Libraries/LibWasm/WASI/Wasi.cpp index 91e097eaf38..587f566eb1c 100644 --- a/Userland/Libraries/LibWasm/WASI/Wasi.cpp +++ b/Userland/Libraries/LibWasm/WASI/Wasi.cpp @@ -313,6 +313,8 @@ static ErrorOr copy_string_excluding_terminating_null(Configuration& con } static Errno errno_value_from_errno(int value); +static FileType file_type_of(struct stat const& buf); +static FDFlags fd_flags_of(struct stat const& buf); Vector const& Implementation::arguments() const { @@ -778,6 +780,38 @@ ErrorOr> Implementation::impl$fd_read(Configuration& configuration, return bytes_read; } +ErrorOr> Implementation::impl$fd_fdstat_get(Configuration&, FD fd) +{ + auto mapped_fd = map_fd(fd); + auto resolved_fd = -1; + mapped_fd.visit( + [&](PreopenedDirectoryDescriptor descriptor) { + auto& entry = preopened_directories()[descriptor.value()]; + resolved_fd = entry.opened_fd.value_or_lazy_evaluated([&] { + ByteString path = entry.host_path.string(); + return open(path.characters(), O_DIRECTORY, 0); + }); + entry.opened_fd = resolved_fd; + }, + [&](u32 fd) { + resolved_fd = fd; + }, + [](UnmappedDescriptor) {}); + if (resolved_fd < 0) + return errno_value_from_errno(errno); + + struct stat stat_buf; + if (fstat(resolved_fd, &stat_buf) < 0) + return errno_value_from_errno(errno); + + return FDStat { + .fs_filetype = file_type_of(stat_buf), + .fs_flags = fd_flags_of(stat_buf), + .fs_rights_base = Rights { .data = 0 }, + .fs_rights_inheriting = Rights { .data = 0 }, + }; +} + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -788,7 +822,6 @@ ErrorOr> Implementation::impl$clock_res_get(Configuration&, Cl ErrorOr> Implementation::impl$fd_advise(Configuration&, FD, FileSize offset, FileSize len, Advice) { return Errno::NoSys; } ErrorOr> Implementation::impl$fd_allocate(Configuration&, FD, FileSize offset, FileSize len) { return Errno::NoSys; } ErrorOr> Implementation::impl$fd_datasync(Configuration&, FD) { return Errno::NoSys; } -ErrorOr> Implementation::impl$fd_fdstat_get(Configuration&, FD) { return Errno::NoSys; } ErrorOr> Implementation::impl$fd_fdstat_set_flags(Configuration&, FD, FDFlags) { return Errno::NoSys; } ErrorOr> Implementation::impl$fd_fdstat_set_rights(Configuration&, FD, Rights fs_rights_base, Rights fs_rights_inheriting) { return Errno::NoSys; } ErrorOr> Implementation::impl$fd_filestat_set_size(Configuration&, FD, FileSize) { return Errno::NoSys; } @@ -1123,6 +1156,33 @@ Errno errno_value_from_errno(int value) return Errno::Invalid; } } + +FileType file_type_of(struct stat const& buf) +{ + switch (buf.st_mode & S_IFMT) { + case S_IFDIR: + return FileType::Directory; + case S_IFCHR: + return FileType::CharacterDevice; + case S_IFBLK: + return FileType::BlockDevice; + case S_IFREG: + return FileType::RegularFile; + case S_IFIFO: + return FileType::Unknown; // FIXME: FileType::Pipe is currently not present in WASI (but it should be) so we use Unknown for now. + case S_IFLNK: + return FileType::SymbolicLink; + case S_IFSOCK: + return FileType::SocketStream; + default: + return FileType::Unknown; + } +} +FDFlags fd_flags_of(struct stat const&) +{ + FDFlags::Bits result {}; + return FDFlags { result }; +} } namespace AK {