xml_term_edit: use libc for file I/O

Ref #91
This commit is contained in:
Emery Hemingway
2017-10-26 11:34:26 -05:00
parent dbd6962ebf
commit f79aa89f7e
3 changed files with 61 additions and 128 deletions

View File

@@ -105,7 +105,7 @@ append config {
<resource name="RAM" quantum="2M"/> <resource name="RAM" quantum="2M"/>
<provides><service name="Terminal"/></provides> <provides><service name="Terminal"/></provides>
<config> <config>
<keyboard layout="us"/> <keyboard layout="none"/>
</config> </config>
<route> <route>
<any-service> <parent/> <any-child/> </any-service> <any-service> <parent/> <any-child/> </any-service>

View File

@@ -13,17 +13,22 @@
/* Genode includes */ /* Genode includes */
#include <os/reporter.h> #include <os/reporter.h>
#include <vfs/file_system_factory.h>
#include <vfs/dir_file_system.h>
#include <terminal_session/connection.h> #include <terminal_session/connection.h>
#include <base/attached_rom_dataspace.h> #include <base/attached_rom_dataspace.h>
#include <base/heap.h> #include <base/heap.h>
#include <base/component.h> #include <libc/component.h>
/* Cli_monitor includes */ /* Cli_monitor includes */
#include <command_line.h> #include <command_line.h>
#include <line_editor.h> #include <line_editor.h>
/* Libc includes */
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
namespace Xml_term_edit { namespace Xml_term_edit {
using namespace Genode; using namespace Genode;
@@ -36,94 +41,46 @@ namespace Xml_term_edit {
struct Main; struct Main;
} }
Genode::Env *_env;
struct Xml_term_edit::Command : Cli_monitor::Command struct Xml_term_edit::Command : Cli_monitor::Command
{ {
Vfs::Dir_file_system &vfs;
Genode::Allocator &alloc; Genode::Allocator &alloc;
Reporter &report; Reporter &report;
Vfs::Vfs_handle *root_handle = nullptr;
Command(char const *name, Command(char const *name,
char const *desc, char const *desc,
Command_registry &cmds, Command_registry &cmds,
Vfs::Dir_file_system &vfs,
Genode::Allocator &alloc, Genode::Allocator &alloc,
Reporter &report) Reporter &report)
: :
Cli_monitor::Command(name, desc), Cli_monitor::Command(name, desc),
vfs(vfs), alloc(alloc), report(report) alloc(alloc), report(report)
{ {
auto r = vfs.open(
"/", Vfs::Directory_service::OPEN_MODE_RDONLY, &root_handle, alloc);
if (r != Vfs::Directory_service::Open_result::OPEN_OK) {
Genode::error("failed to open VFS root directory");
throw r;
}
cmds.insert(this); cmds.insert(this);
} }
/**
* TODO: this is too slow, cache it
*/
void _for_each_argument(Argument_fn const &fn) const override void _for_each_argument(Argument_fn const &fn) const override
{ {
typedef Vfs::File_io_service::Read_result Result; DIR *dirp = opendir("/");
if (dirp == NULL) {
Genode::error("failed to read root directory");
return;
}
enum { DIRENT_COUNT = 4096 / sizeof(Vfs::Directory_service::Dirent) }; dirent *dp;
Vfs::Directory_service::Dirent dirents[DIRENT_COUNT]; while ((dp = readdir(dirp)) != NULL) {
memset(dirents, 0x00, sizeof(dirents)); if (dp->d_type == DT_REG) {
fn(Argument(dp->d_name, ""));
root_handle->seek(0);
for (;;) {
while (!vfs.queue_read(root_handle, sizeof(dirents))) {
_env->ep().wait_and_dispatch_one_io_signal();
}
Vfs::file_size read_count = 0;
Result r;
for (;;) {
r = vfs.complete_read(
root_handle, (char*)&dirents, sizeof(dirents), read_count);
if (r == Result::READ_QUEUED) {
_env->ep().wait_and_dispatch_one_io_signal();
}
else
break;
}
if (r != Result::READ_OK) {
Genode::error("failed to read subsystems");
return;
}
if (read_count == 0) return;
root_handle->advance_seek(read_count);
read_count = read_count / sizeof(Vfs::Directory_service::Dirent);
for (unsigned i = 0; i < read_count; i++) {
Vfs::Directory_service::Dirent const &e = dirents[i];
switch (e.type) {
case Vfs::Directory_service::DIRENT_TYPE_FILE:
/* check if the VFS returned junk */
if (e.name[0] != '\0')
fn(Argument(e.name, ""));
break;
case Vfs::Directory_service::DIRENT_TYPE_END:
return;
default:
break;
}
} }
} }
closedir(dirp);
} }
void insert_file_content(Command_line &cmd, Xml_generator gen) void insert_file_content(Command_line &cmd, Xml_generator gen)
{ {
using namespace Vfs;
Path<128> path; Path<128> path;
Vfs_handle *handle;
{ {
char name[128] = { '\0' }; char name[128] = { '\0' };
if (cmd.argument(0, name, sizeof(name)) == false) { if (cmd.argument(0, name, sizeof(name)) == false) {
@@ -133,41 +90,24 @@ struct Xml_term_edit::Command : Cli_monitor::Command
path.import(name); path.import(name);
} }
Directory_service::Stat sb; int fd = open(path.base(), O_RDONLY);
vfs.stat(path.base(), sb); if (fd == -1) {
Genode::error("failed to open '", path, "'");
/* XXX: error handling */
if (!sb.size)
return;
typedef Directory_service::Open_result Open_result;
Open_result res = vfs.open(
path.base(),
Directory_service::OPEN_MODE_RDONLY,
&handle,
alloc);
switch (res) {
case Open_result::OPEN_OK:
break;
default:
error("failed to open '", path, "'");
/* XXX: log and write error info to the terminal */
return; return;
} }
Vfs_handle::Guard guard(handle);
char buf[1024]; char buf[1024];
file_size offset = 0; for (;;) {
while (offset < sb.size) { auto n = read(fd, buf, sizeof(buf));
file_size n = 0; if (n > 0) {
file_size count = min(sizeof(buf), sb.size-offset); gen.append(buf, n);
handle->fs().complete_read(handle, buf, count, n); } else {
if (!n) if (n < 0)
return; Genode::error("failed to read '", path, "'");
gen.append(buf, n); break;
offset += n; }
handle->advance_seek(n);
} }
close(fd);
} }
}; };
@@ -175,10 +115,9 @@ struct Xml_term_edit::Command : Cli_monitor::Command
struct Xml_term_edit::Add_command : Xml_term_edit::Command struct Xml_term_edit::Add_command : Xml_term_edit::Command
{ {
Add_command(Command_registry &cmds, Add_command(Command_registry &cmds,
Vfs::Dir_file_system &vfs,
Genode::Allocator &alloc, Genode::Allocator &alloc,
Reporter &report) Reporter &report)
: Command("add", "add a new subsystem to init", cmds, vfs, alloc, report) : Command("add", "add a new subsystem to init", cmds, alloc, report)
{ } { }
void execute(Command_line &cmd, Terminal::Session &terminal) override void execute(Command_line &cmd, Terminal::Session &terminal) override
@@ -193,10 +132,9 @@ struct Xml_term_edit::Add_command : Xml_term_edit::Command
struct Xml_term_edit::Del_command : Xml_term_edit::Command struct Xml_term_edit::Del_command : Xml_term_edit::Command
{ {
Del_command(Command_registry &cmds, Del_command(Command_registry &cmds,
Vfs::Dir_file_system &vfs,
Genode::Allocator &alloc, Genode::Allocator &alloc,
Reporter &report) Reporter &report)
: Command("del", "delete a subsystem from init", cmds, vfs, alloc, report) : Command("del", "delete a subsystem from init", cmds, alloc, report)
{ } { }
void execute(Command_line &cmd, Terminal::Session &terminal) override void execute(Command_line &cmd, Terminal::Session &terminal) override
@@ -237,18 +175,8 @@ struct Xml_term_edit::Main
} }
} }
struct Io_response_handler : Vfs::Io_response_handler
{
void handle_io_response(Vfs::Vfs_handle::Context *) override { }
} io_response_handler;
Heap heap { env.ram(), env.rm() }; Heap heap { env.ram(), env.rm() };
Vfs::Global_file_system_factory vfs_factory { heap };
Vfs::Dir_file_system vfs_root {
env, heap, vfs_config(), io_response_handler, vfs_factory };
Terminal::Connection term { env, "edit" }; Terminal::Connection term { env, "edit" };
Reporter reporter { env, "xml_editor", "edit", env.ram().avail_ram().value / 2 }; Reporter reporter { env, "xml_editor", "edit", env.ram().avail_ram().value / 2 };
@@ -265,8 +193,8 @@ struct Xml_term_edit::Main
return nullptr; return nullptr;
} }
Add_command add_command { cmds, vfs_root, heap, reporter }; Add_command add_command { cmds, heap, reporter };
Del_command del_command { cmds, vfs_root, heap, reporter }; Del_command del_command { cmds, heap, reporter };
Exit_command exit_command { cmds, env.parent() }; Exit_command exit_command { cmds, env.parent() };
enum { COMMAND_MAX_LEN = 1024 }; enum { COMMAND_MAX_LEN = 1024 };
@@ -290,24 +218,29 @@ struct Xml_term_edit::Main
void Xml_term_edit::Main::handle_term() void Xml_term_edit::Main::handle_term()
{ {
while (term.avail() && !editor.completed()) { Libc::with_libc([&] () {
char c = 0;
term.read(&c, 1);
editor.submit_input(c);
}
if (editor.completed()) { while (term.avail() && !editor.completed()) {
auto *cmd = lookup_command(cmd_buf); char c = 0;
if (cmd) { term.read(&c, 1);
Cli_monitor::Command_line cmd_line(cmd_buf, *cmd); editor.submit_input(c);
cmd->execute(cmd_line, term);
} }
editor.reset();
} if (editor.completed()) {
auto *cmd = lookup_command(cmd_buf);
if (cmd) {
Cli_monitor::Command_line cmd_line(cmd_buf, *cmd);
cmd->execute(cmd_line, term);
}
editor.reset();
}
});
} }
void Component::construct(Genode::Env &env) void Libc::Component::construct(Libc::Env &env)
{ {
_env = &env; Libc::with_libc([&] () {
static Xml_term_edit::Main inst(env); static Xml_term_edit::Main inst(env);
});
} }

View File

@@ -1,5 +1,5 @@
TARGET = xml_term_edit TARGET = xml_term_edit
SRC_CC = component.cc SRC_CC = component.cc
LIBS = base vfs LIBS = base libc
INC_DIR += $(PRG_DIR) $(call select_from_repositories,src/app/cli_monitor) INC_DIR += $(PRG_DIR) $(call select_from_repositories,src/app/cli_monitor)