diff --git a/doc/components.txt b/doc/components.txt index ae77ff8ec..6aee3f32b 100644 --- a/doc/components.txt +++ b/doc/components.txt @@ -314,6 +314,9 @@ Separate components: :'os/src/server/terminal_log': Adapter for forwarding LOG messages to a terminal session. +:'libports/src/server/fs_log': + Adapter that writes LOG messages to files on a file system. + :'demo/src/server/nitlog': Provides a LOG session, printing log output on screen via a nitpicker session. diff --git a/libports/src/server/fs_log/README b/libports/src/server/fs_log/README new file mode 100644 index 000000000..315d96bbd --- /dev/null +++ b/libports/src/server/fs_log/README @@ -0,0 +1,18 @@ +LOG server that writes log messages onto a file system. + +Using this component, log messages of different processes can be redirected +to files on a file-system service. The assignment of processes to files can +be expressed in the configuration as follows: + +! +! +! +! +! +! +! +! + +In this example, all messages originating from the noux process are directed +to the file '/noux.log'. All messages originating from children of the noux +process end up in the file '/noux_process.log'. diff --git a/libports/src/server/fs_log/main.cc b/libports/src/server/fs_log/main.cc new file mode 100644 index 000000000..d7b485e46 --- /dev/null +++ b/libports/src/server/fs_log/main.cc @@ -0,0 +1,170 @@ +/* + * \brief LOG service that writes to a file + * \author Alexander Tarasikov + * \author Norman Feske + * \date 2013-05-07 + */ + +/* + * Copyright (C) 2013 Ksys Labs LLC + * Copyright (C) 2012-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* libc includes */ +#include +#include + + +class Log_component : public Genode::Rpc_object +{ + public: + + enum { LABEL_LEN = 64 }; + + private: + + typedef Genode::size_t size_t; + + char _label[LABEL_LEN]; + size_t _label_len; + int _fd; + + public: + + /** + * Constructor + */ + Log_component(const char *label, char const *filename) + : + _fd(::open(filename, O_CREAT | O_WRONLY | O_APPEND)) + { + using namespace Genode; + + if (_fd < 0) { + PERR("unable to open \"%s\"", filename); + throw Root::Unavailable(); + } + + snprintf(_label, LABEL_LEN, "[%s] ", label); + _label_len = strlen(_label); + + PINF("log client \"%s\" to file \"%s\")", label, filename); + } + + /** + * Destructor + */ + ~Log_component() { ::close(_fd); } + + + /***************** + ** Log session ** + *****************/ + + /** + * Write a log-message to the file. + */ + size_t write(String const &string_buf) + { + if (!(string_buf.is_valid_string())) { + PERR("corrupted string"); + return 0; + } + + char const *string = string_buf.string(); + Genode::size_t const len = Genode::strlen(string); + + ::write(_fd, _label, _label_len); + ::write(_fd, string, len); + + return len; + } +}; + + +class Log_root : public Genode::Root_component +{ + private: + + int _fd; + + protected: + + /** + * Root component interface + */ + Log_component *_create_session(const char *args) + { + using namespace Genode; + + char label_buf[Log_component::LABEL_LEN]; + Arg label_arg = Arg_string::find_arg(args, "label"); + label_arg.string(label_buf, sizeof(label_buf), ""); + + /* obtain file name from configured policy */ + enum { FILENAME_MAX_LEN = 256 }; + char filename[FILENAME_MAX_LEN]; + try { + Session_policy policy(args); + policy.attribute("file").value(filename, sizeof(filename)); + } catch (...) { + PERR("Invalid session request, no matching policy"); + throw Root::Unavailable(); + } + + return new (md_alloc()) Log_component(label_buf, filename); + } + + public: + + /** + * Constructor + * + * \param session_ep entry point for managing cpu session objects + * \param md_alloc meta-data allocator to be used by root component + */ + Log_root(Genode::Rpc_entrypoint *session_ep, Genode::Allocator *md_alloc) + : Genode::Root_component(session_ep, md_alloc) { } +}; + + +int main(int argc, char **argv) +{ + using namespace Genode; + + /* + * Initialize server entry point + * + * Use a large stack because we are calling libc functions from the + * context of the entrypoint. + */ + enum { STACK_SIZE = sizeof(addr_t)*16*1024 }; + static Cap_connection cap; + static Rpc_entrypoint ep(&cap, STACK_SIZE, "fs_log_ep"); + + static Log_root log_root(&ep, env()->heap()); + + /* + * Announce services + */ + env()->parent()->announce(ep.manage(&log_root)); + + /** + * Got to sleep forever + */ + sleep_forever(); + return 0; +} diff --git a/libports/src/server/fs_log/target.mk b/libports/src/server/fs_log/target.mk new file mode 100644 index 000000000..d3640b9a3 --- /dev/null +++ b/libports/src/server/fs_log/target.mk @@ -0,0 +1,3 @@ +TARGET = fs_log +SRC_CC = main.cc +LIBS = base libc_fs libc