mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-20 06:07:59 +00:00
os: add print_lines utility
The code originates from the report_rom server. This patch makes the code easy to reuse in other components.
This commit is contained in:
parent
32a227ce77
commit
c8ec7b6ffb
96
repos/os/include/util/print_lines.h
Normal file
96
repos/os/include/util/print_lines.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* \brief Utility for safely writing multi-line text
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2014-01-11
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE__OS__PRINT_LINES_H_
|
||||||
|
#define _INCLUDE__OS__PRINT_LINES_H_
|
||||||
|
|
||||||
|
#include <util/string.h>
|
||||||
|
|
||||||
|
namespace Genode {
|
||||||
|
|
||||||
|
template <size_t, typename FUNC>
|
||||||
|
static inline void print_lines(char const *, size_t, FUNC const &);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print multi-line string
|
||||||
|
*
|
||||||
|
* \param MAX_LINE_LEN maximum line length, used to dimension a line buffer
|
||||||
|
* on the stack
|
||||||
|
* \param string character buffer, not necessarily null-terminated
|
||||||
|
* \param len number of characters to print
|
||||||
|
* \param func functor called for each line with 'char const *' as
|
||||||
|
* argument
|
||||||
|
*
|
||||||
|
* In situations where a string is supplied by an untrusted client, we cannot
|
||||||
|
* simply print the client-provided content as a single string becausewe cannot
|
||||||
|
* expect the client to null-terminate the string properly. The 'Log_multiline'
|
||||||
|
* class outputs the content line by line while keeping track of the content
|
||||||
|
* size.
|
||||||
|
*
|
||||||
|
* The output stops when reaching the end of the buffer or when a null
|
||||||
|
* character is encountered.
|
||||||
|
*/
|
||||||
|
template <Genode::size_t MAX_LINE_LEN, typename FUNC>
|
||||||
|
void Genode::print_lines(char const *string, size_t len, FUNC const &func)
|
||||||
|
{
|
||||||
|
/* skip leading line breaks */
|
||||||
|
for (; *string == '\n'; string++);
|
||||||
|
|
||||||
|
/* number of space and tab characters used for indentation */
|
||||||
|
size_t const num_indent_chars =
|
||||||
|
({
|
||||||
|
size_t n = 0;
|
||||||
|
for (; string[n] == ' ' || string[n] == '\t'; n++);
|
||||||
|
n;
|
||||||
|
});
|
||||||
|
|
||||||
|
char const * const first_line = string;
|
||||||
|
|
||||||
|
while (*string && len) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip indentation if the pattern is the same as for the first line.
|
||||||
|
*/
|
||||||
|
if (Genode::strcmp(first_line, string, num_indent_chars) == 0)
|
||||||
|
string += num_indent_chars;
|
||||||
|
|
||||||
|
size_t const line_len =
|
||||||
|
({
|
||||||
|
size_t i = 0;
|
||||||
|
for (; string[i] && i < len && string[i] != '\n'; i++);
|
||||||
|
|
||||||
|
/* the newline character belongs to the line */
|
||||||
|
if (string[i] == '\n')
|
||||||
|
i++;
|
||||||
|
|
||||||
|
i;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!line_len)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy line from (untrusted) caller to local line buffer
|
||||||
|
*/
|
||||||
|
char line_buf[MAX_LINE_LEN];
|
||||||
|
Genode::strncpy(line_buf, string, Genode::min(line_len + 1, sizeof(line_buf)));
|
||||||
|
func(line_buf);
|
||||||
|
|
||||||
|
string += line_len;
|
||||||
|
len -= line_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__OS__PRINT_LINES_H_ */
|
@ -18,6 +18,7 @@
|
|||||||
#include <util/arg_string.h>
|
#include <util/arg_string.h>
|
||||||
#include <report_session/report_session.h>
|
#include <report_session/report_session.h>
|
||||||
#include <root/component.h>
|
#include <root/component.h>
|
||||||
|
#include <os/print_lines.h>
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include <rom_registry.h>
|
#include <rom_registry.h>
|
||||||
@ -41,18 +42,6 @@ struct Report::Session_component : Genode::Rpc_object<Session>, Rom::Writer
|
|||||||
|
|
||||||
bool &_verbose;
|
bool &_verbose;
|
||||||
|
|
||||||
size_t const _str_line_end(char const * const str, size_t const len)
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
for (; str[i] && i < len && str[i] != '\n'; i++);
|
|
||||||
|
|
||||||
/* the newline character belongs to the line */
|
|
||||||
if (str[i] == '\n')
|
|
||||||
i++;
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rom::Module &_create_module(Rom::Module::Name const &name)
|
Rom::Module &_create_module(Rom::Module::Name const &name)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -62,6 +51,12 @@ struct Report::Session_component : Genode::Rpc_object<Session>, Rom::Writer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _log_lines(char const *string, size_t len)
|
||||||
|
{
|
||||||
|
Genode::print_lines<200>(string, len,
|
||||||
|
[&] (char const *line) { PLOG(" %s", line); });
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Session_component(Rom::Module::Name const &name, size_t buffer_size,
|
Session_component(Rom::Module::Name const &name, size_t buffer_size,
|
||||||
@ -91,41 +86,8 @@ struct Report::Session_component : Genode::Rpc_object<Session>, Rom::Writer
|
|||||||
length = Genode::min(length, _ds.size());
|
length = Genode::min(length, _ds.size());
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
|
|
||||||
PLOG("report '%s'", _module.name().string());
|
PLOG("report '%s'", _module.name().string());
|
||||||
|
_log_lines(_ds.local_addr<char>(), length);
|
||||||
/*
|
|
||||||
* We cannot simply print the content of the report dataspace
|
|
||||||
* as one string because we cannot expect the client to null-
|
|
||||||
* terminate the content properly. Therefore, we output the
|
|
||||||
* report line by line while keeping track of the dataspace
|
|
||||||
* size.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* pointer and length of remaining string */
|
|
||||||
char const *str = _ds.local_addr<char>();
|
|
||||||
size_t len = length;
|
|
||||||
|
|
||||||
while (*str && len) {
|
|
||||||
|
|
||||||
size_t const line_len = _str_line_end(str, len);
|
|
||||||
|
|
||||||
if (!line_len)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy line from (untrusted) report dataspace to local
|
|
||||||
* line buffer,
|
|
||||||
*/
|
|
||||||
char line_buf[200];
|
|
||||||
Genode::strncpy(line_buf, str, Genode::min(line_len, sizeof(line_buf)));
|
|
||||||
PLOG(" %s", line_buf);
|
|
||||||
|
|
||||||
str += line_len;
|
|
||||||
len -= line_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
PLOG("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_module.write_content(_ds.local_addr<char>(), length);
|
_module.write_content(_ds.local_addr<char>(), length);
|
||||||
|
Loading…
Reference in New Issue
Block a user