mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[6s] Allow 6s to know about filesystems
Added a j6_proto_vfs_tag/_get_tag pair of messages to the VFS protocol to allow filesystems to label themselves, and gave 6s the concept of current fs and current working directory.
This commit is contained in:
@@ -8,4 +8,6 @@ enum j6_proto_vfs_tag
|
||||
{
|
||||
j6_proto_vfs_load = j6_proto_base_first_proto_id,
|
||||
j6_proto_vfs_file,
|
||||
};
|
||||
j6_proto_vfs_get_tag,
|
||||
j6_proto_vfs_tag,
|
||||
};
|
||||
|
||||
@@ -13,7 +13,13 @@ class API client
|
||||
public:
|
||||
/// Constructor.
|
||||
/// \arg vfs_mb Handle to the VFS service's mailbox
|
||||
client(j6_handle_t vfs_mb);
|
||||
client(j6_handle_t vfs_mb = 0);
|
||||
|
||||
/// Copy constructor
|
||||
client(const client& c);
|
||||
|
||||
/// Check if this client's handle is valid
|
||||
inline bool valid() const { return m_service != j6_handle_invalid; }
|
||||
|
||||
/// Load a file into a VMA
|
||||
/// \arg path Path of the file to load
|
||||
@@ -21,8 +27,13 @@ public:
|
||||
/// \arg size [out] Size of the file
|
||||
j6_status_t load_file(char *path, j6_handle_t &vma, size_t &size);
|
||||
|
||||
/// Get fs tag
|
||||
/// \arg tag [out] The filesystem's tag
|
||||
/// \arg size [inout] Size of the input buffer, length of the returned string
|
||||
j6_status_t get_tag(char *tag, size_t &len);
|
||||
|
||||
private:
|
||||
j6_handle_t m_service;
|
||||
};
|
||||
|
||||
} // namespace j6::proto::vfs
|
||||
} // namespace j6::proto::vfs
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "j6/types.h"
|
||||
#include <j6/errors.h>
|
||||
#include <j6/protocols/vfs.hh>
|
||||
#include <j6/syscalls.h>
|
||||
@@ -12,6 +13,11 @@ client::client(j6_handle_t vfs_mb) :
|
||||
{
|
||||
}
|
||||
|
||||
client::client(const client& c) :
|
||||
m_service {c.m_service}
|
||||
{
|
||||
}
|
||||
|
||||
inline size_t simple_strlen(const char *s) { size_t n = 0; while (s && *s) s++, n++; return n; }
|
||||
|
||||
j6_status_t
|
||||
@@ -61,5 +67,31 @@ client::load_file(char *path, j6_handle_t &vma, size_t &size)
|
||||
}
|
||||
|
||||
|
||||
j6_status_t
|
||||
client::get_tag(char *tag, size_t &len)
|
||||
{
|
||||
if (len < sizeof(j6_status_t))
|
||||
return j6_err_insufficient;
|
||||
|
||||
uint64_t message_tag = j6_proto_vfs_get_tag;
|
||||
size_t handle_count = 0;
|
||||
|
||||
size_t in_len = 0;
|
||||
j6_status_t s = j6_mailbox_call(m_service, &message_tag,
|
||||
tag, &in_len, len, nullptr, &handle_count, 0);
|
||||
|
||||
if (s != j6_status_ok)
|
||||
return s;
|
||||
|
||||
if (message_tag == j6_proto_base_status)
|
||||
return *reinterpret_cast<j6_status_t*>(tag); // contains a status
|
||||
|
||||
if (message_tag != j6_proto_vfs_tag)
|
||||
return j6_err_unexpected;
|
||||
|
||||
len = in_len;
|
||||
return j6_status_ok; // data is now in `tag` and `len`
|
||||
}
|
||||
|
||||
} // namespace j6::proto::vfs
|
||||
#endif // __j6kernel
|
||||
|
||||
@@ -7,4 +7,5 @@ module("6s",
|
||||
sources = [
|
||||
"commands.cpp",
|
||||
"main.cpp",
|
||||
"shell.cpp",
|
||||
])
|
||||
|
||||
@@ -1,23 +1,45 @@
|
||||
#include <edit/line.h>
|
||||
#include <util/format.h>
|
||||
#include "commands.h"
|
||||
#include "shell.h"
|
||||
|
||||
static void
|
||||
help(edit::source &s)
|
||||
fslist(shell &s)
|
||||
{
|
||||
char line[100];
|
||||
util::counted<char> output { line, sizeof(line) };
|
||||
|
||||
for (auto &f : s.filesystems()) {
|
||||
size_t len = util::format(output, "%s\r\n", f.tag);
|
||||
s.write(line, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
help(shell &s)
|
||||
{
|
||||
char line[100];
|
||||
util::counted<char> output { line, sizeof(line) };
|
||||
|
||||
for (unsigned i = 0; i < g_builtins_count; ++i) {
|
||||
char line[100];
|
||||
util::counted<char> output { line, sizeof(line) };
|
||||
|
||||
builtin &cmd = g_builtins[i];
|
||||
|
||||
size_t len = util::format(output, "%20s - %s\r\n", cmd.name(), cmd.description());
|
||||
s.write(line, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
version(edit::source &s)
|
||||
pwd(shell &s)
|
||||
{
|
||||
char line[100];
|
||||
util::counted<char> output { line, sizeof(line) };
|
||||
|
||||
size_t len = util::format(output, "%s:%s\r\n", s.cfs(), s.cwd());
|
||||
s.write(line, len);
|
||||
}
|
||||
|
||||
static void
|
||||
version(shell &s)
|
||||
{
|
||||
static const char *gv = GIT_VERSION;
|
||||
|
||||
@@ -29,7 +51,9 @@ version(edit::source &s)
|
||||
}
|
||||
|
||||
builtin g_builtins[] = {
|
||||
{ "help", "list availble commands", help },
|
||||
{ "fslist", "list available filesystems", fslist },
|
||||
{ "help", "list available commands", help },
|
||||
{ "pwd", "print current working directory", pwd },
|
||||
{ "version", "print current jsix version", version },
|
||||
};
|
||||
size_t g_builtins_count = sizeof(g_builtins) / sizeof(g_builtins[0]);
|
||||
|
||||
@@ -2,15 +2,12 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace edit {
|
||||
class source;
|
||||
}
|
||||
|
||||
struct shell;
|
||||
|
||||
class builtin
|
||||
{
|
||||
public:
|
||||
using runf = void (*)(edit::source &);
|
||||
using runf = void (*)(shell &);
|
||||
|
||||
builtin(const char *name, const char *desc, runf func) :
|
||||
m_name {name}, m_desc {desc}, m_func {func} {}
|
||||
@@ -18,7 +15,7 @@ public:
|
||||
const char * name() const { return m_name; }
|
||||
const char * description() const { return m_desc; }
|
||||
|
||||
void run(edit::source &s) { m_func(s); }
|
||||
void run(shell &s) { m_func(s); }
|
||||
|
||||
private:
|
||||
const char *m_name;
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
#include <j6/types.h>
|
||||
#include <edit/line.h>
|
||||
|
||||
#include "commands.h"
|
||||
#include "shell.h"
|
||||
|
||||
extern "C" {
|
||||
int main(int, const char **);
|
||||
}
|
||||
|
||||
j6_handle_t g_handle_sys = j6_handle_invalid;
|
||||
//j6_handle_t g_handle_sys = j6_handle_invalid;
|
||||
|
||||
const char prompt[] = "\x1b[1;32mj6> \x1b[0m";
|
||||
static constexpr size_t prompt_len = sizeof(prompt) - 1;
|
||||
@@ -31,7 +31,6 @@ const char greeting[] = "\x1b[2J\x1b[H\x1b[1;30m\
|
||||
|
||||
static constexpr size_t greeting_len = sizeof(greeting) - 1;
|
||||
|
||||
void handle_command(edit::source &s, const char *command, size_t len);
|
||||
|
||||
class channel_source :
|
||||
public edit::source
|
||||
@@ -47,9 +46,13 @@ public:
|
||||
|
||||
void write(char const *data, size_t len) override {
|
||||
uint8_t *outp;
|
||||
m_chan.reserve(len, &outp);
|
||||
memcpy(outp, data, len);
|
||||
m_chan.commit(len);
|
||||
while (len) {
|
||||
size_t size = m_chan.reserve(len, &outp);
|
||||
size_t n = len < size ? len : size;
|
||||
memcpy(outp, data, n);
|
||||
m_chan.commit(n);
|
||||
len -= n;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -63,14 +66,20 @@ main(int argc, const char **argv)
|
||||
j6_handle_t event = j6_handle_invalid;
|
||||
j6_status_t result = j6_status_ok;
|
||||
|
||||
/*
|
||||
g_handle_sys = j6_find_init_handle(0);
|
||||
if (g_handle_sys == j6_handle_invalid)
|
||||
return 1;
|
||||
*/
|
||||
|
||||
j6_handle_t slp = j6_find_init_handle(j6::proto::sl::id);
|
||||
if (slp == j6_handle_invalid)
|
||||
return 3;
|
||||
|
||||
j6_handle_t vfs = j6_find_init_handle(j6::proto::vfs::id);
|
||||
if (vfs == j6_handle_invalid)
|
||||
return 4;
|
||||
|
||||
uint64_t proto_id = "jsix.protocol.stream.ouput"_id;
|
||||
j6::proto::sl::client slp_client {slp};
|
||||
|
||||
@@ -95,6 +104,9 @@ main(int argc, const char **argv)
|
||||
channel_source source {*cout};
|
||||
edit::line editor {source};
|
||||
|
||||
shell sh { source };
|
||||
sh.add_filesystem(vfs);
|
||||
|
||||
static constexpr size_t bufsize = 256;
|
||||
char buffer [bufsize];
|
||||
|
||||
@@ -102,25 +114,6 @@ main(int argc, const char **argv)
|
||||
|
||||
while (true) {
|
||||
size_t len = editor.read(buffer, bufsize, prompt, prompt_len);
|
||||
handle_command(source, buffer, len);
|
||||
sh.handle_command(buffer, len);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_command(edit::source &s, const char *command, size_t len)
|
||||
{
|
||||
j6::syslog(j6::logs::app, j6::log_level::info, "Command: %s", command);
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < g_builtins_count; ++i) {
|
||||
builtin &cmd = g_builtins[i];
|
||||
if (strncmp(command, cmd.name(), len) == 0) {
|
||||
cmd.run(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const char unknown[] = "\x1b[1;33mUnknown command.\x1b[0m\r\n";
|
||||
s.write(unknown, sizeof(unknown)-1);
|
||||
}
|
||||
|
||||
43
src/user/6s/shell.cpp
Normal file
43
src/user/6s/shell.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include <string.h>
|
||||
#include <j6/errors.h>
|
||||
#include <j6/syslog.hh>
|
||||
#include "commands.h"
|
||||
#include "shell.h"
|
||||
|
||||
void
|
||||
shell::add_filesystem(j6_handle_t mb)
|
||||
{
|
||||
char tag_buf [100];
|
||||
size_t size = sizeof(tag_buf);
|
||||
j6::proto::vfs::client c {mb};
|
||||
j6_status_t s = c.get_tag(tag_buf, size);
|
||||
if (s != j6_status_ok)
|
||||
return;
|
||||
|
||||
char *name = new char [size + 1];
|
||||
memcpy(name, tag_buf, size);
|
||||
name[size] = 0;
|
||||
|
||||
m_fs.push_back({name, c});
|
||||
if (!m_cfs)
|
||||
m_cfs = name;
|
||||
}
|
||||
|
||||
void
|
||||
shell::handle_command(const char *command, size_t len)
|
||||
{
|
||||
j6::syslog(j6::logs::app, j6::log_level::info, "Command: %s", command);
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < g_builtins_count; ++i) {
|
||||
builtin &cmd = g_builtins[i];
|
||||
if (strncmp(command, cmd.name(), len) == 0) {
|
||||
cmd.run(*this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const char unknown[] = "\x1b[1;33mUnknown command.\x1b[0m\r\n";
|
||||
write(unknown, sizeof(unknown)-1);
|
||||
}
|
||||
38
src/user/6s/shell.h
Normal file
38
src/user/6s/shell.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <j6/protocols/vfs.hh>
|
||||
#include <edit/line.h>
|
||||
|
||||
/// Shell state
|
||||
class shell
|
||||
{
|
||||
public:
|
||||
struct fs {
|
||||
const char *tag;
|
||||
j6::proto::vfs::client client;
|
||||
};
|
||||
using fs_list = std::vector<fs>;
|
||||
|
||||
shell(edit::source &source) : m_source {source}, m_cwd {"/"}, m_cfs {nullptr} {}
|
||||
|
||||
const char * cwd() const { return m_cwd; }
|
||||
const char * cfs() const { return m_cfs; }
|
||||
|
||||
// Transparently use source read/write functions
|
||||
inline void consume(size_t len) { m_source.consume(len); }
|
||||
inline void write(char const *data, size_t len) { m_source.write(data, len); }
|
||||
inline size_t read(char const **data) { return m_source.read(data); }
|
||||
|
||||
void add_filesystem(j6_handle_t mb);
|
||||
inline const fs_list & filesystems() const { return m_fs; }
|
||||
|
||||
void handle_command(const char *command, size_t len);
|
||||
|
||||
private:
|
||||
edit::source &m_source;
|
||||
|
||||
char m_cwd [256];
|
||||
char const *m_cfs;
|
||||
fs_list m_fs;
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <stdint.h>
|
||||
#include <j6/flags.h>
|
||||
#include <j6/errors.h>
|
||||
#include <j6/memutils.h>
|
||||
#include <j6/protocols/vfs.h>
|
||||
#include <j6/syscalls.h>
|
||||
#include <j6/syslog.hh>
|
||||
@@ -11,6 +12,9 @@
|
||||
static uint64_t initfs_running = 1;
|
||||
static constexpr size_t buffer_size = 2048;
|
||||
|
||||
static char fs_tag[] = "init";
|
||||
static constexpr size_t fs_tag_len = sizeof(fs_tag) - 1;
|
||||
|
||||
j6_status_t
|
||||
handle_load_request(j6romfs::fs &fs, const char *path, j6_handle_t &vma)
|
||||
{
|
||||
@@ -82,6 +86,14 @@ initfs_start(j6romfs::fs &fs, j6_handle_t mb)
|
||||
tag = j6_proto_vfs_file;
|
||||
break;
|
||||
|
||||
case j6_proto_vfs_get_tag:
|
||||
out_len = fs_tag_len;
|
||||
handles_count = 0;
|
||||
tag = j6_proto_vfs_tag;
|
||||
memcpy(buffer, fs_tag, fs_tag_len);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
tag = j6_proto_base_status;
|
||||
*reinterpret_cast<j6_status_t*>(buffer) = j6_err_invalid_arg;
|
||||
@@ -90,7 +102,6 @@ initfs_start(j6romfs::fs &fs, j6_handle_t mb)
|
||||
handles_count = 0;
|
||||
}
|
||||
|
||||
out_len = buffer_size;
|
||||
s = j6_mailbox_respond(mb, &tag,
|
||||
buffer, &out_len, buffer_size,
|
||||
&give_handle, &handles_count, max_handles,
|
||||
|
||||
Reference in New Issue
Block a user