W7 done done
This commit is contained in:
@@ -19,6 +19,7 @@ uce_host_zip
|
||||
uce_host_units
|
||||
uce_host_component_resolve
|
||||
uce_host_request_perf
|
||||
uce_host_shell_exec
|
||||
uce_host_file_exists
|
||||
uce_host_file_read
|
||||
uce_host_file_write
|
||||
@@ -26,5 +27,16 @@ uce_host_file_unlink
|
||||
uce_host_file_list
|
||||
uce_host_file_mkdir
|
||||
uce_host_file_mtime
|
||||
uce_host_file_open_locked
|
||||
uce_host_file_close_locked
|
||||
uce_host_file_release_process_locks
|
||||
uce_host_file_read_locked_fd
|
||||
uce_host_file_write_locked_fd
|
||||
uce_host_path_real
|
||||
uce_host_path_is_within
|
||||
uce_host_cwd_get
|
||||
uce_host_cwd_set
|
||||
uce_host_process_start_directory
|
||||
uce_host_last_trap_trace
|
||||
uce_host_regex
|
||||
uce_host_sqlite
|
||||
|
||||
+167
-1
@@ -40,6 +40,9 @@
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <vector>
|
||||
@@ -428,21 +431,32 @@ public:
|
||||
request_perf.active = true;
|
||||
}
|
||||
|
||||
// Host-owned opaque fd handles opened by wasm file_open_locked().
|
||||
std::vector<int> locked_file_handles;
|
||||
|
||||
#ifdef UCE_WASM_HOST_CONNECTORS
|
||||
// Host-owned resource handle table (§3.1): connections opened by the guest
|
||||
// live here and are closed when the workspace drops at request end.
|
||||
std::vector<SQLite*> sqlite_handles;
|
||||
std::vector<MySQL*> mysql_handles;
|
||||
#endif
|
||||
~WasmWorkspace()
|
||||
{
|
||||
for(int fd : locked_file_handles)
|
||||
if(fd >= 0)
|
||||
{
|
||||
flock(fd, LOCK_UN);
|
||||
::close(fd);
|
||||
}
|
||||
#ifdef UCE_WASM_HOST_CONNECTORS
|
||||
for(auto* db : sqlite_handles)
|
||||
if(db)
|
||||
delete db; // ~SQLite disconnects
|
||||
for(auto* db : mysql_handles)
|
||||
if(db)
|
||||
delete db; // ~MySQL disconnects
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// The guest calls a sized hostcall twice (buf=0 to learn the length, then
|
||||
// to fetch). For side-effecting ops (sqlite) re-executing on the fetch is
|
||||
@@ -1304,6 +1318,77 @@ private:
|
||||
fprintf(stderr, "[guest log %d] %.*s\n", args[0].i32(), (int)text.size(), text.data());
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_shell_exec")
|
||||
return(add([self](Caller caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
String cmd;
|
||||
self->hostcall_read(args[0].i32(), args[1].i32(), cmd);
|
||||
String out;
|
||||
if(!self->hostcall_staged("shell:" + cmd, out))
|
||||
{
|
||||
out = ::shell_exec(cmd);
|
||||
self->hostcall_stage("shell:" + cmd, out);
|
||||
}
|
||||
u32 cap = (u32)args[3].i32();
|
||||
int32_t buf = args[2].i32();
|
||||
if(buf != 0 && cap >= out.size())
|
||||
self->hostcall_write(buf, out);
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
results[0] = Val((int32_t)out.size());
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_path_real")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
String path;
|
||||
self->hostcall_read(args[0].i32(), args[1].i32(), path);
|
||||
String resolved = ::path_real(path);
|
||||
u32 cap = (u32)args[3].i32();
|
||||
int32_t buf = args[2].i32();
|
||||
if(buf != 0 && cap >= resolved.size())
|
||||
self->hostcall_write(buf, resolved);
|
||||
results[0] = Val((int32_t)resolved.size());
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_path_is_within")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
String path, root;
|
||||
self->hostcall_read(args[0].i32(), args[1].i32(), path);
|
||||
self->hostcall_read(args[2].i32(), args[3].i32(), root);
|
||||
results[0] = Val(::path_is_within(path, root) ? (int32_t)1 : (int32_t)0);
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_cwd_get")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
String cwd = ::cwd_get();
|
||||
u32 cap = (u32)args[1].i32();
|
||||
int32_t buf = args[0].i32();
|
||||
if(buf != 0 && cap >= cwd.size())
|
||||
self->hostcall_write(buf, cwd);
|
||||
results[0] = Val((int32_t)cwd.size());
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_cwd_set")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
String path;
|
||||
self->hostcall_read(args[0].i32(), args[1].i32(), path);
|
||||
results[0] = Val(::chdir(path.c_str()) == 0 ? (int32_t)1 : (int32_t)0);
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_process_start_directory")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
String cwd = ::process_start_directory();
|
||||
u32 cap = (u32)args[1].i32();
|
||||
int32_t buf = args[0].i32();
|
||||
if(buf != 0 && cap >= cwd.size())
|
||||
self->hostcall_write(buf, cwd);
|
||||
results[0] = Val((int32_t)cwd.size());
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_last_trap_trace")
|
||||
return(add([](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
(void)args;
|
||||
results[0] = Val((int32_t)0);
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_file_exists")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
String path, current;
|
||||
@@ -1340,6 +1425,87 @@ private:
|
||||
results[0] = Val((int64_t)mtime);
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_file_open_locked")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
String path, purpose;
|
||||
self->hostcall_read(args[0].i32(), args[1].i32(), path);
|
||||
self->hostcall_read(args[6].i32(), args[7].i32(), purpose);
|
||||
int fd = ::file_open_locked(path, args[2].i32(), args[3].i32(), args[4].i32(), args[5].f64(), purpose);
|
||||
int handle = -1;
|
||||
if(fd >= 0)
|
||||
{
|
||||
for(size_t i = 0; i < self->locked_file_handles.size(); i++)
|
||||
if(self->locked_file_handles[i] < 0)
|
||||
{
|
||||
self->locked_file_handles[i] = fd;
|
||||
handle = (int)i + 1;
|
||||
break;
|
||||
}
|
||||
if(handle < 0)
|
||||
{
|
||||
self->locked_file_handles.push_back(fd);
|
||||
handle = (int)self->locked_file_handles.size();
|
||||
}
|
||||
}
|
||||
results[0] = Val((int32_t)handle);
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_file_close_locked")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val>) -> Result<std::monostate, Trap> {
|
||||
int handle = args[0].i32();
|
||||
if(handle >= 1 && (size_t)handle <= self->locked_file_handles.size())
|
||||
{
|
||||
int& fd = self->locked_file_handles[(size_t)handle - 1];
|
||||
if(fd >= 0)
|
||||
{
|
||||
::file_close_locked(fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_file_release_process_locks")
|
||||
return(add([self](Caller, Span<const Val>, Span<Val>) -> Result<std::monostate, Trap> {
|
||||
for(int& fd : self->locked_file_handles)
|
||||
if(fd >= 0)
|
||||
{
|
||||
::file_close_locked(fd);
|
||||
fd = -1;
|
||||
}
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_file_read_locked_fd")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
int handle = args[0].i32();
|
||||
String content;
|
||||
if(handle >= 1 && (size_t)handle <= self->locked_file_handles.size())
|
||||
{
|
||||
int fd = self->locked_file_handles[(size_t)handle - 1];
|
||||
if(fd >= 0)
|
||||
content = ::file_get_contents_locked_fd(fd);
|
||||
}
|
||||
u32 cap = (u32)args[2].i32();
|
||||
int32_t buf = args[1].i32();
|
||||
if(buf != 0 && cap >= content.size())
|
||||
self->hostcall_write(buf, content);
|
||||
results[0] = Val((int32_t)content.size());
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_file_write_locked_fd")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
int handle = args[0].i32();
|
||||
String content;
|
||||
self->hostcall_read(args[1].i32(), args[2].i32(), content);
|
||||
bool ok = false;
|
||||
if(handle >= 1 && (size_t)handle <= self->locked_file_handles.size())
|
||||
{
|
||||
int fd = self->locked_file_handles[(size_t)handle - 1];
|
||||
if(fd >= 0)
|
||||
ok = ::file_put_contents_locked_fd(fd, content);
|
||||
}
|
||||
results[0] = Val(ok ? (int32_t)1 : (int32_t)0);
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_file_read")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
String path, current;
|
||||
|
||||
Reference in New Issue
Block a user