Remove dependency on libzip in libretro builds

This commit is contained in:
刘皓 2025-03-31 13:26:54 -04:00
parent 12f12d91a1
commit dcd29f44a9
No known key found for this signature in database
GPG key ID: 7901753DB465B711
7 changed files with 9 additions and 758 deletions

View file

@ -23,15 +23,11 @@
#include <algorithm>
#include <random>
#include <sstream>
#include <zip.h>
#include <mkxp-retro-ruby.h>
#include "filesystem.h"
#include "core.h"
#include "wasi.h"
extern const uint8_t mkxp_retro_dist_zip[];
extern const size_t mkxp_retro_dist_zip_len;
//#define WASI_DEBUG(...) mkxp_retro::log_printf(RETRO_LOG_INFO, __VA_ARGS__)
#define WASI_DEBUG(...)
@ -50,81 +46,13 @@ struct FileSystem::File *wasi_file_entry::file_handle() {
return (struct FileSystem::File *)handle;
}
struct wasi_zip_handle *wasi_file_entry::zip_handle() {
return (wasi_zip_handle *)handle;
}
struct wasi_zip_dir_handle *wasi_file_entry::zip_dir_handle() {
return (wasi_zip_dir_handle *)handle;
}
struct wasi_zip_file_handle *wasi_file_entry::zip_file_handle() {
return (wasi_zip_file_handle *)handle;
}
static std::vector<path_cache_entry_t> compute_path_cache(zip_t *zip) {
if (zip == NULL) {
return std::vector<path_cache_entry_t>();
}
std::vector<path_cache_entry_t> path_cache;
zip_int64_t num_entries = zip_get_num_entries(zip, 0);
for (zip_int64_t i = 0; i < num_entries; ++i) {
std::string name(zip_get_name(zip, i, 0));
if (!name.empty() && name.back() == '/') {
name.pop_back();
}
u32 n_slashes = 0;
for (u32 i = 0; i < name.length(); ++i) {
if (name[i] == '/') {
++n_slashes;
}
}
path_cache.push_back({n_slashes, name});
}
std::sort(path_cache.begin(), path_cache.end());
return path_cache;
}
wasi_zip_container::wasi_zip_container() : source(NULL), zip(NULL), path_cache(compute_path_cache(zip)) {}
wasi_zip_container::wasi_zip_container(const char *path, zip_flags_t flags) : source(NULL), zip(zip_open(path, flags, NULL)), path_cache(compute_path_cache(zip)) {}
wasi_zip_container::wasi_zip_container(const void *buffer, zip_uint64_t length, zip_flags_t flags) : source(zip_source_buffer_create(buffer, length, 0, NULL)), zip(source == NULL ? NULL : zip_open_from_source(source, flags, NULL)), path_cache(compute_path_cache(zip)) {}
wasi_zip_container::~wasi_zip_container() {
if (zip != NULL) {
zip_close(zip);
} else if (source != NULL) {
zip_source_close(source);
}
}
wasi_zip_file_container::wasi_zip_file_container() : file(NULL) {}
wasi_zip_file_container::wasi_zip_file_container(wasi_zip_container &zip, zip_uint64_t index, zip_flags_t flags) : file(zip_fopen_index(zip.zip, index, flags)) {}
wasi_zip_file_container::~wasi_zip_file_container() {
if (file != NULL) {
zip_fclose(file);
}
}
wasi_t::w2c_wasi__snapshot__preview1(std::shared_ptr<struct w2c_ruby> ruby) : ruby(ruby), dist(new wasi_zip_container(mkxp_retro_dist_zip, mkxp_retro_dist_zip_len, ZIP_RDONLY)) {
if (dist->zip == NULL) {
throw SandboxTrapException();
}
wasi_t::w2c_wasi__snapshot__preview1(std::shared_ptr<struct w2c_ruby> ruby) : ruby(ruby) {
// Initialize WASI file descriptor table
fdtable.push_back({.type = wasi_fd_type::STDIN});
fdtable.push_back({.type = wasi_fd_type::STDOUT});
fdtable.push_back({.type = wasi_fd_type::STDERR});
fdtable.push_back({.type = wasi_fd_type::ZIP, .handle = new (struct wasi_zip_handle){.zip = dist, .path = "/mkxp-retro-dist"}});
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new std::string("/mkxp-retro-game")});
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new std::string("/mkxp-retro-dist")});
}
wasi_t::~w2c_wasi__snapshot__preview1() {
@ -134,81 +62,6 @@ wasi_t::~w2c_wasi__snapshot__preview1() {
}
}
// Gets information about a file or directory at a certain path within a zip file.
static struct wasi_zip_stat wasi_zip_stat(zip_t *zip, const char *path, u32 path_len) {
struct wasi_zip_stat info;
zip_stat_t stat;
info.normalized_path = mkxp_retro::fs->normalize(path, false, false);
if (info.normalized_path.length() == 0) {
info.exists = true;
info.filetype = WASI_IFDIR;
info.inode = -1;
info.size = 0;
info.mtime = 0;
return info;
}
if (zip_stat(zip, info.normalized_path.c_str(), 0, &stat) == 0) {
info.exists = true;
info.filetype = WASI_IFREG;
info.inode = stat.index;
info.size = stat.size;
info.mtime = stat.mtime * 1000000000L;
return info;
}
info.normalized_path.push_back('/');
if (zip_stat(zip, info.normalized_path.c_str(), 0, &stat) == 0) {
info.exists = true;
info.filetype = WASI_IFDIR;
info.inode = stat.index;
info.size = stat.size;
info.mtime = stat.mtime * 1000000000L;
return info;
}
info.exists = false;
return info;
}
// Gets information about a file or directory at a certain index within a zip file.
static struct wasi_zip_stat wasi_zip_stat_entry(zip_t *zip, struct wasi_file_entry &entry) {
struct wasi_zip_stat info;
zip_stat_t stat;
switch (entry.type) {
case wasi_fd_type::ZIPDIR:
if (zip_stat_index(zip, entry.zip_dir_handle()->index, 0, &stat) == 0) {
info.exists = true;
info.filetype = WASI_IFDIR;
info.inode = stat.index;
info.size = stat.size;
info.mtime = stat.mtime * 1000000000L;
} else {
info.exists = false;
}
return info;
case wasi_fd_type::ZIPFILE:
if (zip_stat_index(zip, entry.zip_file_handle()->index, 0, &stat) == 0) {
info.exists = true;
info.filetype = WASI_IFREG;
info.inode = stat.index;
info.size = stat.size;
info.mtime = stat.mtime * 1000000000L;
} else {
info.exists = false;
}
return info;
default:
info.exists = false;
return info;
}
}
struct fs_enumerate_data {
wasi_t *wasi;
u32 fd;
@ -242,15 +95,6 @@ void wasi_t::deallocate_file_descriptor(u32 fd) {
case wasi_fd_type::FSFILE:
delete fdtable[fd].file_handle();
break;
case wasi_fd_type::ZIP:
delete fdtable[fd].zip_handle();
break;
case wasi_fd_type::ZIPDIR:
delete fdtable[fd].zip_dir_handle();
break;
case wasi_fd_type::ZIPFILE:
delete fdtable[fd].zip_file_handle();
break;
default:
break;
}
@ -320,13 +164,9 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_close(wasi_t *wasi, u32 fd) {
case wasi_fd_type::STDOUT:
case wasi_fd_type::STDERR:
case wasi_fd_type::FS:
case wasi_fd_type::ZIP:
return WASI_EINVAL;
case wasi_fd_type::FSDIR:
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIPDIR:
case wasi_fd_type::ZIPFILE:
wasi->deallocate_file_descriptor(fd);
return WASI_ESUCCESS;
}
@ -354,7 +194,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_fdstat_get(wasi_t *wasi, u32 fd,
case wasi_fd_type::STDOUT:
case wasi_fd_type::STDERR:
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIPFILE:
WASM_SET(u8, result, WASI_IFCHR); // fs_filetype
WASM_SET(u16, result + 2, 0); // fs_flags
WASM_SET(u64, result + 8, WASI_FD_READ | WASI_FD_WRITE | WASI_FD_FILESTAT_GET); // fs_rights_base
@ -363,8 +202,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_fdstat_get(wasi_t *wasi, u32 fd,
case wasi_fd_type::FS:
case wasi_fd_type::FSDIR:
case wasi_fd_type::ZIP:
case wasi_fd_type::ZIPDIR:
WASM_SET(u8, result, WASI_IFDIR); // fs_filetype
WASM_SET(u16, result + 2, 0); // fs_flags
WASM_SET(u64, result + 8, WASI_PATH_OPEN | WASI_FD_READDIR | WASI_PATH_FILESTAT_GET | WASI_FD_FILESTAT_GET); // fs_rights_base
@ -392,9 +229,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_fdstat_set_flags(wasi_t *wasi, u3
case wasi_fd_type::FS:
case wasi_fd_type::FSDIR:
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIP:
case wasi_fd_type::ZIPDIR:
case wasi_fd_type::ZIPFILE:
return WASI_ESUCCESS;
}
@ -465,47 +299,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_filestat_get(wasi_t *wasi, u32 fd
WASM_SET(u64, result + 56, stat.createtime * 1000000000L); // ctim
return WASI_ESUCCESS;
}
case wasi_fd_type::ZIP:
{
struct wasi_zip_stat info = wasi_zip_stat(wasi->fdtable[fd].zip_handle()->zip->zip, "", 0);
if (!info.exists) {
return WASI_ENOENT;
}
WASM_SET(u64, result, fd); // dev
WASM_SET(u64, result + 8, info.inode); // ino
WASM_SET(u8, result + 16, info.filetype); // filetype
WASM_SET(u32, result + 24, 1); // nlink
WASM_SET(u64, result + 32, info.size); // size
WASM_SET(u64, result + 40, info.mtime); // atim
WASM_SET(u64, result + 48, info.mtime); // mtim
WASM_SET(u64, result + 56, info.mtime); // ctim
return WASI_ESUCCESS;
}
case wasi_fd_type::ZIPDIR:
case wasi_fd_type::ZIPFILE:
{
u32 parent_fd = wasi->fdtable[fd].type == wasi_fd_type::ZIPDIR
? wasi->fdtable[fd].zip_dir_handle()->parent_fd
: wasi->fdtable[fd].zip_file_handle()->parent_fd;
struct wasi_zip_stat info = wasi_zip_stat_entry(
wasi->fdtable[parent_fd].zip_handle()->zip->zip,
wasi->fdtable[fd]
);
if (!info.exists) {
return WASI_ENOENT;
}
WASM_SET(u64, result, parent_fd); // dev
WASM_SET(u64, result + 8, info.inode); // ino
WASM_SET(u8, result + 16, info.filetype); // filetype
WASM_SET(u32, result + 24, 1); // nlink
WASM_SET(u64, result + 32, info.size); // size
WASM_SET(u64, result + 40, info.mtime); // atim
WASM_SET(u64, result + 48, info.mtime); // mtim
WASM_SET(u64, result + 56, info.mtime); // ctim
return WASI_ESUCCESS;
}
}
return WASI_EBADF;
@ -551,17 +344,11 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_prestat_dir_name(wasi_t *wasi, u3
std::strncpy((char *)WASM_MEM(path), wasi->fdtable[fd].dir_handle()->c_str(), path_len);
return WASI_ESUCCESS;
case wasi_fd_type::ZIP:
std::strncpy((char *)WASM_MEM(path), wasi->fdtable[fd].zip_handle()->path.c_str(), path_len);
return WASI_ESUCCESS;
case wasi_fd_type::STDIN:
case wasi_fd_type::STDOUT:
case wasi_fd_type::STDERR:
case wasi_fd_type::FSDIR:
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIPDIR:
case wasi_fd_type::ZIPFILE:
return WASI_EINVAL;
}
@ -584,18 +371,11 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_prestat_get(wasi_t *wasi, u32 fd,
WASM_SET(u32, result + 4, wasi->fdtable[fd].dir_handle()->length());
return WASI_ESUCCESS;
case wasi_fd_type::ZIP:
WASM_SET(u32, result, 0);
WASM_SET(u32, result + 4, wasi->fdtable[fd].zip_handle()->path.length());
return WASI_ESUCCESS;
case wasi_fd_type::STDIN:
case wasi_fd_type::STDOUT:
case wasi_fd_type::STDERR:
case wasi_fd_type::FSDIR:
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIPDIR:
case wasi_fd_type::ZIPFILE:
return WASI_EINVAL;
}
@ -626,8 +406,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_read(wasi_t *wasi, u32 fd, usize
case wasi_fd_type::FS:
case wasi_fd_type::FSDIR:
case wasi_fd_type::ZIP:
case wasi_fd_type::ZIPDIR:
return WASI_EINVAL;
case wasi_fd_type::FSFILE:
@ -643,20 +421,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_read(wasi_t *wasi, u32 fd, usize
WASM_SET(u32, result, size);
return WASI_ESUCCESS;
}
case wasi_fd_type::ZIPFILE:
{
u32 size = 0;
while (iovs_len > 0) {
zip_int64_t n = zip_fread(wasi->fdtable[fd].zip_file_handle()->zip_file_handle.file, WASM_MEM(WASM_GET(u32, iovs)), WASM_GET(u32, iovs + 4));
if (n < 0) return WASI_EIO;
size += n;
iovs += 8;
--iovs_len;
}
WASM_SET(u32, result, size);
return WASI_ESUCCESS;
}
}
return WASI_EBADF;
@ -677,7 +441,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_readdir(wasi_t *wasi, u32 fd, usi
case wasi_fd_type::STDOUT:
case wasi_fd_type::STDERR:
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIPFILE:
return WASI_EINVAL;
case wasi_fd_type::FS:
@ -748,88 +511,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_readdir(wasi_t *wasi, u32 fd, usi
}
return success ? WASI_ESUCCESS : WASI_ENOENT;
}
case wasi_fd_type::ZIP:
case wasi_fd_type::ZIPDIR:
{
usize original_buf = buf;
std::string *prefix = wasi->fdtable[fd].type == wasi_fd_type::ZIP ? NULL : &wasi->fdtable[fd].zip_dir_handle()->path;
u32 n_slashes = 0;
if (prefix != NULL) {
for (u32 i = 0; i < prefix->length(); ++i) {
if ((*prefix)[i] == '/') {
++n_slashes;
}
}
}
std::shared_ptr<struct wasi_zip_container> zip = wasi->fdtable[fd].type == wasi_fd_type::ZIP
? wasi->fdtable[fd].zip_handle()->zip
: wasi->fdtable[wasi->fdtable[fd].zip_dir_handle()->parent_fd].zip_handle()->zip;
auto it = std::lower_bound(
zip->path_cache.begin(),
zip->path_cache.end(),
prefix == NULL ? std::make_pair(n_slashes, "") : std::make_pair(n_slashes, *prefix)
);
it += cookie;
while (it != zip->path_cache.end() && it->first == n_slashes && (prefix == NULL || std::strncmp(it->second.c_str(), prefix->c_str(), prefix->length()) == 0)) {
++cookie;
struct wasi_zip_stat info = wasi_zip_stat(
wasi->fdtable[fd].type == wasi_fd_type::ZIP
? wasi->fdtable[fd].zip_handle()->zip->zip
: wasi->fdtable[wasi->fdtable[fd].zip_dir_handle()->parent_fd].zip_handle()->zip->zip,
it->second.c_str(),
it->second.length()
);
if (!info.exists) {
++it;
continue;
}
u32 suffix_length = it->second.length() - (prefix == NULL ? 0 : prefix->length());
if (buf - original_buf + 8 > buf_len) {
WASM_SET(u32, result, buf - original_buf);
return WASI_ESUCCESS;
}
WASM_SET(u64, buf, cookie);
buf += 8;
if (buf - original_buf + 8 > buf_len) {
WASM_SET(u32, result, buf - original_buf);
return WASI_ESUCCESS;
}
WASM_SET(u64, buf, info.inode);
buf += 8;
if (buf - original_buf + 4 > buf_len) {
WASM_SET(u32, result, buf - original_buf);
return WASI_ESUCCESS;
}
WASM_SET(u32, buf, suffix_length);
buf += 4;
if (buf - original_buf + 4 > buf_len) {
WASM_SET(u32, result, buf - original_buf);
return WASI_ESUCCESS;
}
WASM_SET(u8, buf, info.filetype);
buf += 4;
u32 len = std::min(suffix_length, original_buf + buf_len - buf);
std::memcpy(WASM_MEM(buf), it->second.c_str() + (prefix == NULL ? 0 : prefix->length()), len);
buf += len;
++it;
}
WASM_SET(u32, result, buf - original_buf);
return WASI_ESUCCESS;
}
}
return WASI_EBADF;
@ -850,13 +531,10 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_renumber(wasi_t *wasi, u32 fd, u3
case wasi_fd_type::STDOUT:
case wasi_fd_type::STDERR:
case wasi_fd_type::FS:
case wasi_fd_type::ZIP:
return WASI_EINVAL;
case wasi_fd_type::FSDIR:
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIPDIR:
case wasi_fd_type::ZIPFILE:
break;
}
@ -874,13 +552,10 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_renumber(wasi_t *wasi, u32 fd, u3
case wasi_fd_type::STDOUT:
case wasi_fd_type::STDERR:
case wasi_fd_type::FS:
case wasi_fd_type::ZIP:
return WASI_EINVAL;
case wasi_fd_type::FSDIR:
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIPDIR:
case wasi_fd_type::ZIPFILE:
wasi->deallocate_file_descriptor(to);
if (to == wasi->fdtable.size()) {
wasi->fdtable.push_back(wasi->fdtable[fd]);
@ -925,17 +600,11 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_tell(wasi_t *wasi, u32 fd, usize
case wasi_fd_type::STDERR:
case wasi_fd_type::FS:
case wasi_fd_type::FSDIR:
case wasi_fd_type::ZIP:
case wasi_fd_type::ZIPDIR:
return WASI_EINVAL;
case wasi_fd_type::FSFILE:
WASM_SET(u64, result, PHYSFS_tell(wasi->fdtable[fd].file_handle()->get()));
return WASI_ESUCCESS;
case wasi_fd_type::ZIPFILE:
WASM_SET(u64, result, zip_ftell(wasi->fdtable[fd].zip_file_handle()->zip_file_handle.file));
return WASI_ESUCCESS;
}
return WASI_EBADF;
@ -978,12 +647,9 @@ extern "C" u32 w2c_wasi__snapshot__preview1_fd_write(wasi_t *wasi, u32 fd, usize
case wasi_fd_type::FS:
case wasi_fd_type::FSDIR:
case wasi_fd_type::ZIP:
case wasi_fd_type::ZIPDIR:
return WASI_EINVAL;
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIPFILE:
return WASI_EROFS;
}
@ -1010,7 +676,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_path_filestat_get(wasi_t *wasi, u32
case wasi_fd_type::STDOUT:
case wasi_fd_type::STDERR:
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIPFILE:
return WASI_EINVAL;
case wasi_fd_type::FS:
@ -1042,42 +707,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_path_filestat_get(wasi_t *wasi, u32
WASM_SET(u64, result + 56, stat.createtime * 1000000000L); // ctim
return WASI_ESUCCESS;
}
case wasi_fd_type::ZIP:
{
struct wasi_zip_stat info = wasi_zip_stat(wasi->fdtable[fd].zip_handle()->zip->zip, (char *)WASM_MEM(path), path_len);
if (!info.exists) {
return WASI_ENOENT;
}
WASM_SET(u64, result, fd); // dev
WASM_SET(u64, result + 8, info.inode); // ino
WASM_SET(u8, result + 16, info.filetype); // filetype
WASM_SET(u32, result + 24, 1); // nlink
WASM_SET(u64, result + 32, info.size); // size
WASM_SET(u64, result + 40, info.mtime); // atim
WASM_SET(u64, result + 48, info.mtime); // mtim
WASM_SET(u64, result + 56, info.mtime); // ctim
return WASI_ESUCCESS;
}
case wasi_fd_type::ZIPDIR:
{
std::string new_path(wasi->fdtable[fd].zip_dir_handle()->path);
new_path.append((const char *)WASM_MEM(path), strlen_safe((const char *)WASM_MEM(path), path_len));
struct wasi_zip_stat info = wasi_zip_stat(wasi->fdtable[wasi->fdtable[fd].zip_dir_handle()->parent_fd].zip_handle()->zip->zip, new_path.c_str(), new_path.length());
if (!info.exists) {
return WASI_ENOENT;
}
WASM_SET(u64, result, wasi->fdtable[fd].zip_dir_handle()->parent_fd); // dev
WASM_SET(u64, result + 8, info.inode); // ino
WASM_SET(u8, result + 16, info.filetype); // filetype
WASM_SET(u32, result + 24, 1); // nlink
WASM_SET(u64, result + 32, info.size); // size
WASM_SET(u64, result + 40, info.mtime); // atim
WASM_SET(u64, result + 48, info.mtime); // mtim
WASM_SET(u64, result + 56, info.mtime); // ctim
return WASI_ESUCCESS;
}
}
return WASI_EBADF;
@ -1108,7 +737,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_path_open(wasi_t *wasi, u32 fd, u32
case wasi_fd_type::STDOUT:
case wasi_fd_type::STDERR:
case wasi_fd_type::FSFILE:
case wasi_fd_type::ZIPFILE:
return WASI_EINVAL;
case wasi_fd_type::FS:
@ -1138,53 +766,6 @@ extern "C" u32 w2c_wasi__snapshot__preview1_path_open(wasi_t *wasi, u32 fd, u32
WASM_SET(u32, result, wasi->allocate_file_descriptor(wasi_fd_type::FSFILE, handle));
}
return WASI_ESUCCESS;
}
case wasi_fd_type::ZIP:
case wasi_fd_type::ZIPDIR:
{
std::string new_path;
if (wasi->fdtable[fd].type == wasi_fd_type::ZIPDIR) {
new_path.append(wasi->fdtable[fd].zip_dir_handle()->path);
}
new_path.append((const char *)WASM_MEM(path), strlen_safe((const char *)WASM_MEM(path), path_len));
struct wasi_zip_stat info = wasi_zip_stat(
wasi->fdtable[fd].type == wasi_fd_type::ZIP
? wasi->fdtable[fd].zip_handle()->zip->zip
: wasi->fdtable[wasi->fdtable[fd].zip_dir_handle()->parent_fd].zip_handle()->zip->zip,
new_path.c_str(),
new_path.length()
);
if (!info.exists) {
return WASI_ENOENT;
}
if (info.filetype == WASI_IFDIR) {
struct wasi_zip_dir_handle *handle = new (struct wasi_zip_dir_handle){
.index = info.inode,
.path = info.normalized_path,
.parent_fd = wasi->fdtable[fd].type == wasi_fd_type::ZIPDIR ? wasi->fdtable[fd].zip_dir_handle()->parent_fd : fd,
};
WASM_SET(u32, result, wasi->allocate_file_descriptor(wasi_fd_type::ZIPDIR, handle));
} else {
struct wasi_zip_file_handle *handle = new (struct wasi_zip_file_handle){
.index = info.inode,
.zip_file_handle = wasi_zip_file_container(
wasi->fdtable[fd].type == wasi_fd_type::ZIP
? *wasi->fdtable[fd].zip_handle()->zip
: *wasi->fdtable[wasi->fdtable[fd].zip_dir_handle()->parent_fd].zip_handle()->zip,
info.inode,
0
),
.parent_fd = wasi->fdtable[fd].type == wasi_fd_type::ZIPDIR ? wasi->fdtable[fd].zip_dir_handle()->parent_fd : fd,
};
WASM_SET(u32, result, wasi->allocate_file_descriptor(wasi_fd_type::ZIPFILE, handle));
}
return WASI_ESUCCESS;
}
}

View file

@ -25,7 +25,6 @@
#include <memory>
#include <string>
#include <vector>
#include <zip.h>
#include "filesystem.h"
#include "types.h"
@ -191,55 +190,15 @@
typedef std::pair<u32, std::string> path_cache_entry_t;
struct wasi_zip_container {
private:
zip_source_t *const source;
public:
zip_t *const zip;
std::vector<path_cache_entry_t> path_cache;
wasi_zip_container();
wasi_zip_container(const char *path, zip_flags_t flags);
wasi_zip_container(const void *buffer, zip_uint64_t length, zip_flags_t flags);
~wasi_zip_container();
};
struct wasi_zip_file_container {
zip_file_t *const file;
wasi_zip_file_container();
wasi_zip_file_container(wasi_zip_container &zip, zip_uint64_t index, zip_flags_t flags);
~wasi_zip_file_container();
};
struct wasi_zip_handle {
std::shared_ptr<struct wasi_zip_container> zip; // Zip handle that can be used with libzip
std::string path; // Mount point of this archive relative to the root of the virtual filesystem, normalized to start with one leading slash and no trailing slashes (e.g. "/example/path")
};
struct wasi_zip_dir_handle {
zip_uint64_t index; // Index of this directory within the zip file
std::string path; // Path of this directory relative to the root of the zip file, normalized to start with no leading slashes or dots and one trailing slash (e.g. "example/path/")
u32 parent_fd; // WASI file descriptor of the zip file that contains this directory
};
struct wasi_zip_file_handle {
zip_uint64_t index; // Index of this file within the zip file
struct wasi_zip_file_container zip_file_handle; // Handle to this file that can be used with libzip
u32 parent_fd; // WASI file descriptor of the zip file that contains this file
};
struct undefined {};
enum wasi_fd_type {
STDIN, // This file descriptor is standard input. The `handle` field is null.
STDOUT, // This file descriptor is standard output. The `handle` field is null.
STDERR, // This file descriptor is standard error. The `handle` field is null.
FS, // This file descriptor is a preopened directory handled by the mkxp-z filesystem code. The `handle` field is a `std::string *` containing the path of the directory.
FSDIR, // This file descriptor is a directory handled by the mkxp-z filesystem code. The `handle` field is a `std::string *` containing the path of the directory.
FSFILE, // This file descriptor is a file handled by the mkxp-z filesystem code. The `handle` field is a `struct FileSystem::File *`.
ZIP, // This file descriptor is a read-only zip file. The `handle` field is a `struct wasi_zip_handle *`.
ZIPDIR, // This file descriptor is a directory inside of a zip file. The `handle` field is a `struct wasi_zip_dir_handle *`.
ZIPFILE, // This file descriptor is a file inside of a zip file. The `handle` field is a `struct wasi_zip_file_handle *`.
FS, // This file descriptor is a preopened directory handled by PhysFS. The `handle` field is a `std::string *` containing the path of the directory.
FSDIR, // This file descriptor is a directory handled by PhysFS. The `handle` field is a `std::string *` containing the path of the directory.
FSFILE, // This file descriptor is a file handled by PhysFS. The `handle` field is a `struct FileSystem::File *`.
VACANT, // Indicates this is a vacant file descriptor that doesn't correspond to a file. The `handle` field is null.
};
@ -251,25 +210,11 @@ struct wasi_file_entry {
std::string *dir_handle();
struct FileSystem::File *file_handle();
struct wasi_zip_handle *zip_handle();
struct wasi_zip_dir_handle *zip_dir_handle();
struct wasi_zip_file_handle *zip_file_handle();
};
struct wasi_zip_stat {
bool exists;
u8 filetype;
u64 inode;
u64 size;
u64 mtime;
std::string normalized_path;
};
typedef struct w2c_wasi__snapshot__preview1 {
std::shared_ptr<struct w2c_ruby> ruby;
std::shared_ptr<struct wasi_zip_container> dist;
// WASI file descriptor table. Maps WASI file descriptors (unsigned 32-bit integers) to file handles.
std::vector<wasi_file_entry> fdtable;

View file

@ -337,30 +337,6 @@ if is_libretro
'ZLIB_BUILD_EXAMPLES': false,
})
libzip_options = cmake.subproject_options()
libzip_options.add_cmake_defines({
'CMAKE_POLICY_VERSION_MINIMUM': '3.5',
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'BUILD_SHARED_LIBS': false,
'LIBZIP_DO_INSTALL': false,
'BUILD_TOOLS': false,
'BUILD_REGRESS': false,
'BUILD_OSSFUZZ': false,
'BUILD_EXAMPLES': false,
'BUILD_DOC': false,
'ENABLE_COMMONCRYPTO': false,
'ENABLE_GNUTLS': false,
'ENABLE_MBEDTLS': false,
'ENABLE_OPENSSL': false,
'ENABLE_WINDOWS_CRYPTO': false,
'ENABLE_FDOPEN': false,
'ENABLE_BZIP2': false,
'ENABLE_LZMA': false,
'ENABLE_ZSTD': false,
})
physfs_options = cmake.subproject_options()
physfs_options.add_cmake_defines({
'CMAKE_POLICY_VERSION_MINIMUM': '3.5',
@ -548,7 +524,6 @@ if is_libretro
cmake.subproject('boost_type_traits', options: boost_options).dependency('boost_type_traits'),
cmake.subproject('boost_optional', options: boost_options).dependency('boost_optional'),
cmake.subproject(host_system == 'darwin' ? 'zlib-darwin' : 'zlib', options: zlib_options).dependency('zlibstatic'),
cmake.subproject('libzip', options: libzip_options).dependency('zip'),
cmake.subproject('physfs', options: physfs_options).dependency('physfs-static'),
cmake.subproject('openal-soft', options: openal_options).dependency('OpenAL'),
cmake.subproject('openal-soft', options: openal_options).dependency('alsoft.fmt'),

View file

@ -77,6 +77,8 @@ static inline void free_align(void *ptr) {
extern const uint8_t mkxp_gmgsx_sf2[];
extern const size_t mkxp_gmgsx_sf2_len;
extern const uint8_t mkxp_retro_dist_zip[];
extern const size_t mkxp_retro_dist_zip_len;
static bool initialized = false;
static ALCdevice *al_device = NULL;
@ -218,6 +220,8 @@ static bool init_sandbox() {
} else if ((rgssad = PHYSFS_openRead("/mkxp-retro-game/Game.rgss3a")) != NULL) {
PHYSFS_mountHandle(rgssad, "Game.rgss3a", "/mkxp-retro-game", 1);
}
PHYSFS_mountMemory(mkxp_retro_dist_zip, mkxp_retro_dist_zip_len, NULL, "mkxp-retro-dist.zip", "/mkxp-retro-dist", 1);
}
fs->createPathCache();

View file

@ -1,5 +0,0 @@
[wrap-git]
url = https://github.com/nih-at/libzip
revision = v1.11.2
depth = 1
diff_files = libzip-deps.patch, libzip-emscripten-endian.patch

View file

@ -1,235 +0,0 @@
# This patch prevents libzip's build system from trying to look for zlib, bzip2, lzma and zstd since Meson already handles that.
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -200,64 +200,14 @@ int main(int argc, char *argv[]) { }" HAVE_NULLABLE)
-find_package(ZLIB 1.1.2 REQUIRED)
-# so developers on systems where zlib is named differently (Windows, sometimes)
-# can override the name used in the pkg-config file
-if (NOT ZLIB_LINK_LIBRARY_NAME)
- set(ZLIB_LINK_LIBRARY_NAME "z")
-
- # Get the correct name in common cases
- list(LENGTH ZLIB_LIBRARIES N_ZLIB_LIBRARIES)
- if(N_ZLIB_LIBRARIES EQUAL 1)
- set(ZLIB_FILENAME ${ZLIB_LIBRARIES})
- elseif(N_ZLIB_LIBRARIES EQUAL 4)
- # ZLIB_LIBRARIES might have the target_link_library() format like
- # "optimized;path/to/zlib.lib;debug;path/to/zlibd.lib". Use the 'optimized'
- # case unless we know we are in a Debug build.
- if(CMAKE_BUILD_TYPE STREQUAL "Debug")
- list(FIND ZLIB_LIBRARIES "debug" ZLIB_LIBRARIES_INDEX_OF_CONFIG)
- else()
- list(FIND ZLIB_LIBRARIES "optimized" ZLIB_LIBRARIES_INDEX_OF_CONFIG)
- endif()
- if(ZLIB_LIBRARIES_INDEX_OF_CONFIG GREATER_EQUAL 0)
- math(EXPR ZLIB_FILENAME_INDEX "${ZLIB_LIBRARIES_INDEX_OF_CONFIG}+1")
- list(GET ZLIB_LIBRARIES ${ZLIB_FILENAME_INDEX} ZLIB_FILENAME)
- endif()
- endif()
- if(ZLIB_FILENAME)
- get_filename_component(ZLIB_FILENAME ${ZLIB_FILENAME} NAME_WE)
- string(REGEX REPLACE "^lib" "" ZLIB_LINK_LIBRARY_NAME ${ZLIB_FILENAME})
- endif()
-endif(NOT ZLIB_LINK_LIBRARY_NAME)
-
if(ENABLE_BZIP2)
- find_package(BZip2)
- if(BZIP2_FOUND)
set(HAVE_LIBBZ2 1)
- else()
- message(WARNING "-- bzip2 library not found; bzip2 support disabled")
- endif(BZIP2_FOUND)
endif(ENABLE_BZIP2)
if(ENABLE_LZMA)
- find_package(LibLZMA 5.2)
- if(LIBLZMA_FOUND)
set(HAVE_LIBLZMA 1)
- else()
- message(WARNING "-- lzma library not found; lzma/xz support disabled")
- endif(LIBLZMA_FOUND)
endif(ENABLE_LZMA)
if(ENABLE_ZSTD)
- find_package(zstd 1.4.0)
- if(zstd_FOUND)
set(HAVE_LIBZSTD 1)
- if(TARGET zstd::libzstd_shared AND BUILD_SHARED_LIBS)
- set(zstd_TARGET zstd::libzstd_shared)
- else()
- set(zstd_TARGET zstd::libzstd_static)
- endif()
- else()
- message(WARNING "-- zstd library not found; zstandard support disabled")
- endif(zstd_FOUND)
endif(ENABLE_ZSTD)
if (COMMONCRYPTO_FOUND)
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -140,17 +140,14 @@ endif(WIN32)
if(HAVE_LIBBZ2)
target_sources(zip PRIVATE zip_algorithm_bzip2.c)
- target_link_libraries(zip PRIVATE BZip2::BZip2)
endif()
if(HAVE_LIBLZMA)
target_sources(zip PRIVATE zip_algorithm_xz.c)
- target_link_libraries(zip PRIVATE LibLZMA::LibLZMA)
endif()
if(HAVE_LIBZSTD)
target_sources(zip PRIVATE zip_algorithm_zstd.c)
- target_link_libraries(zip PRIVATE ${zstd_TARGET})
endif()
if(HAVE_COMMONCRYPTO)
@@ -178,7 +175,6 @@ if(SHARED_LIB_VERSIONNING)
set_target_properties(zip PROPERTIES VERSION 5.5 SOVERSION 5 MACHO_CURRENT_VERSION 6.5 MACHO_COMPATIBILITY_VERSION 6)
endif()
-target_link_libraries(zip PRIVATE ZLIB::ZLIB)
target_include_directories(zip
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib>
--- a/lib/compat.h
+++ b/lib/compat.h
@@ -154,7 +154,8 @@ typedef off_t zip_off_t;
#define ZIP_OFF_MAX ZIP_INT16_MAX
#define ZIP_OFF_MIN ZIP_INT16_MIN
#else
-#error unsupported size of off_t
+#define ZIP_OFF_MAX ZIP_INT64_MAX
+#define ZIP_OFF_MIN ZIP_INT64_MIN
#endif
#define ZIP_FSEEK_MAX ZIP_OFF_MAX
--- a/lib/zip_algorithm_bzip2.c
+++ b/lib/zip_algorithm_bzip2.c
@@ -33,7 +33,7 @@
#include "zipint.h"
-#include <bzlib.h>
+#include "../../bzip2/bzlib.h"
#include <limits.h>
#include <stdlib.h>
--- a/lib/zip_algorithm_deflate.c
+++ b/lib/zip_algorithm_deflate.c
@@ -35,7 +35,7 @@
#include <limits.h>
#include <stdlib.h>
-#include <zlib.h>
+#include "../../zlib/zlib.h"
struct ctx {
zip_error_t *error;
--- a/lib/zip_algorithm_xz.c
+++ b/lib/zip_algorithm_xz.c
@@ -35,9 +35,9 @@
#include "zipint.h"
#include <limits.h>
-#include <lzma.h>
+#include "../../liblzma/src/liblzma/api/lzma.h"
#include <stdlib.h>
-#include <zlib.h>
+#include "../../zlib/zlib.h"
enum header_state { INCOMPLETE, OUTPUT, DONE };
--- a/lib/zip_algorithm_zstd.c
+++ b/lib/zip_algorithm_zstd.c
@@ -34,8 +34,8 @@
#include "zipint.h"
#include <stdlib.h>
-#include <zstd.h>
-#include <zstd_errors.h>
+#include "../../zstd/lib/zstd.h"
+#include "../../zstd/lib/zstd_errors.h"
struct ctx {
zip_error_t *error;
--- a/lib/zip_dirent.c
+++ b/lib/zip_dirent.c
@@ -37,7 +37,7 @@
#include <string.h>
#include <sys/types.h>
#include <time.h>
-#include <zlib.h>
+#include "../../zlib/zlib.h"
#include "zipint.h"
--- a/lib/zip_error_strerror.c
+++ b/lib/zip_error_strerror.c
@@ -35,7 +35,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <zlib.h>
+#include "../../zlib/zlib.h"
#include "zipint.h"
--- a/lib/zip_io_util.c
+++ b/lib/zip_io_util.c
@@ -34,7 +34,7 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#include <zlib.h>
+#include "../../zlib/zlib.h"
#include "zipint.h"
--- a/lib/zip_pkware.c
+++ b/lib/zip_pkware.c
@@ -33,7 +33,7 @@
#include <stdlib.h>
-#include <zlib.h>
+#include "../../zlib/zlib.h"
#include "zipint.h"
--- a/lib/zip_source_crc.c
+++ b/lib/zip_source_crc.c
@@ -34,7 +34,7 @@
#include <limits.h>
#include <stdlib.h>
-#include <zlib.h>
+#include "../../zlib/zlib.h"
#include "zipint.h"
--- a/lib/zip_string.c
+++ b/lib/zip_string.c
@@ -34,7 +34,7 @@
#include <stdlib.h>
#include <string.h>
-#include <zlib.h>
+#include "../../zlib/zlib.h"
#include "zipint.h"
--- a/src/zipcmp.c
+++ b/src/zipcmp.c
@@ -45,7 +45,7 @@
#ifdef HAVE_FTS_H
#include <fts.h>
#endif
-#include <zlib.h>
+#include "../../zlib/zlib.h"
#ifndef HAVE_GETOPT
#include "getopt.h"

View file

@ -1,14 +0,0 @@
# Disables checking for endianness when targeting Emscripten because it causes configuration errors, and because we already know Emscripten targets are always little-endian.
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -196,5 +196,8 @@ check_c_source_compiles("
int foo(char * _Nullable bar);
int main(int argc, char *argv[]) { }" HAVE_NULLABLE)
-test_big_endian(WORDS_BIGENDIAN)
+string(TOLOWER ${CMAKE_SYSTEM_NAME} SYSTEM_LOWER)
+if(NOT SYSTEM_LOWER STREQUAL "emscripten")
+ test_big_endian(WORDS_BIGENDIAN)
+endif()