journal: when browsing the journal via browse.html allow clicking on entries to show their details
This commit is contained in:
parent
934a316cbf
commit
c6511e859c
|
@ -580,7 +580,8 @@ MANPAGES_ALIAS = \
|
||||||
man/sd_journal_seek_tail.3 \
|
man/sd_journal_seek_tail.3 \
|
||||||
man/sd_journal_seek_monotonic_usec.3 \
|
man/sd_journal_seek_monotonic_usec.3 \
|
||||||
man/sd_journal_seek_realtime_usec.3 \
|
man/sd_journal_seek_realtime_usec.3 \
|
||||||
man/sd_journal_seek_cursor.3
|
man/sd_journal_seek_cursor.3 \
|
||||||
|
man/sd_journal_test_cursor.3
|
||||||
|
|
||||||
man/reboot.8: man/halt.8
|
man/reboot.8: man/halt.8
|
||||||
man/poweroff.8: man/halt.8
|
man/poweroff.8: man/halt.8
|
||||||
|
@ -649,6 +650,7 @@ man/sd_journal_seek_tail.3: man/sd_journal_seek_head.3
|
||||||
man/sd_journal_seek_monotonic_usec.3: man/sd_journal_seek_head.3
|
man/sd_journal_seek_monotonic_usec.3: man/sd_journal_seek_head.3
|
||||||
man/sd_journal_seek_realtime_usec.3: man/sd_journal_seek_head.3
|
man/sd_journal_seek_realtime_usec.3: man/sd_journal_seek_head.3
|
||||||
man/sd_journal_seek_cursor.3: man/sd_journal_seek_head.3
|
man/sd_journal_seek_cursor.3: man/sd_journal_seek_head.3
|
||||||
|
man/sd_journal_test_cursor.3: man/sd_journal_get_cursor.3
|
||||||
|
|
||||||
XML_FILES = \
|
XML_FILES = \
|
||||||
${patsubst %.1,%.xml,${patsubst %.3,%.xml,${patsubst %.5,%.xml,${patsubst %.7,%.xml,${patsubst %.8,%.xml,$(MANPAGES)}}}}}
|
${patsubst %.1,%.xml,${patsubst %.3,%.xml,${patsubst %.5,%.xml,${patsubst %.7,%.xml,${patsubst %.8,%.xml,$(MANPAGES)}}}}}
|
||||||
|
|
|
@ -44,7 +44,8 @@
|
||||||
|
|
||||||
<refnamediv>
|
<refnamediv>
|
||||||
<refname>sd_journal_get_cursor</refname>
|
<refname>sd_journal_get_cursor</refname>
|
||||||
<refpurpose>Get cursor string for the current journal entry</refpurpose>
|
<refname>sd_journal_test_cursor</refname>
|
||||||
|
<refpurpose>Get cursor string for or test cursor string against the current journal entry</refpurpose>
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
|
@ -57,6 +58,12 @@
|
||||||
<paramdef>char ** <parameter>cursor</parameter></paramdef>
|
<paramdef>char ** <parameter>cursor</parameter></paramdef>
|
||||||
</funcprototype>
|
</funcprototype>
|
||||||
|
|
||||||
|
<funcprototype>
|
||||||
|
<funcdef>int <function>sd_journal_test_cursor</function></funcdef>
|
||||||
|
<paramdef>sd_journal* <parameter>j</parameter></paramdef>
|
||||||
|
<paramdef>const char * <parameter>cursor</parameter></paramdef>
|
||||||
|
</funcprototype>
|
||||||
|
|
||||||
</funcsynopsis>
|
</funcsynopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
@ -66,7 +73,7 @@
|
||||||
<para><function>sd_journal_get_cursor()</function>
|
<para><function>sd_journal_get_cursor()</function>
|
||||||
returns a cursor string for the current journal
|
returns a cursor string for the current journal
|
||||||
entry. A cursor is a serialization of the current
|
entry. A cursor is a serialization of the current
|
||||||
journal position in text form. The string only
|
journal position formatted as text. The string only
|
||||||
contains printable characters and can be passed around
|
contains printable characters and can be passed around
|
||||||
in text form. The cursor identifies a journal entry
|
in text form. The cursor identifies a journal entry
|
||||||
globally and in a stable way and may be used to later
|
globally and in a stable way and may be used to later
|
||||||
|
@ -77,16 +84,33 @@
|
||||||
without the specific entry being available locally
|
without the specific entry being available locally
|
||||||
will seek to the next closest (in terms of time)
|
will seek to the next closest (in terms of time)
|
||||||
available entry. The call takes two arguments: a
|
available entry. The call takes two arguments: a
|
||||||
journal context object and a pointer to a
|
journal context object and a pointer to a string
|
||||||
string pointer where the cursor string will be
|
pointer where the cursor string will be placed. The
|
||||||
placed. The string is allocated via libc <citerefentry><refentrytitle>malloc</refentrytitle><manvolnum>3</manvolnum></citerefentry> and should
|
string is allocated via libc
|
||||||
be freed after use with
|
<citerefentry><refentrytitle>malloc</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||||
|
and should be freed after use with
|
||||||
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
||||||
|
|
||||||
<para>Note that this function will not work before
|
<para>Note that
|
||||||
|
<function>sd_journal_get_cursor()</function> will not
|
||||||
|
work before
|
||||||
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||||
(or related call) has been called at least
|
(or related call) has been called at least once, in
|
||||||
once, in order to position the read pointer at a valid entry.</para>
|
order to position the read pointer at a valid
|
||||||
|
entry.</para>
|
||||||
|
|
||||||
|
<para><function>sd_journal_test_cursor()</function>
|
||||||
|
may be used to check whether the current position in
|
||||||
|
the journal matches the specified cursor. This is
|
||||||
|
useful since cursor strings do not uniquely identify
|
||||||
|
an entry: the same entry might be referred to by
|
||||||
|
multiple different cursor strings, and hence string
|
||||||
|
comparing cursors is not possible. Use this call to
|
||||||
|
verify after an invocation of
|
||||||
|
<citerefentry><refentrytitle>sd_journal_seek_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||||
|
whether the entry being seeked to was actually found
|
||||||
|
in the journal or the next closest entry was used
|
||||||
|
instead.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@ -94,15 +118,20 @@
|
||||||
|
|
||||||
<para><function>sd_journal_get_cursor()</function>
|
<para><function>sd_journal_get_cursor()</function>
|
||||||
returns 0 on success or a negative errno-style error
|
returns 0 on success or a negative errno-style error
|
||||||
code.</para>
|
code. <function>sd_journal_test_cursor()</function>
|
||||||
|
returns positive if the current entry matches the
|
||||||
|
specified cursor, 0 if it doesn't match the specified
|
||||||
|
cursor or a negative errno-style error code on
|
||||||
|
failure.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Notes</title>
|
<title>Notes</title>
|
||||||
|
|
||||||
<para>The <function>sd_journal_get_cursor()</function>
|
<para>The <function>sd_journal_get_cursor()</function>
|
||||||
interface is available as shared library, which can be
|
and <function>sd_journal_test_cursor()</function>
|
||||||
compiled and linked to with the
|
interfaces are available as shared library, which can
|
||||||
|
be compiled and linked to with the
|
||||||
<literal>libsystemd-journal</literal>
|
<literal>libsystemd-journal</literal>
|
||||||
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||||
file.</para>
|
file.</para>
|
||||||
|
|
|
@ -115,7 +115,12 @@
|
||||||
<para><function>sd_journal_seek_cursor()</function>
|
<para><function>sd_journal_seek_cursor()</function>
|
||||||
seeks to the entry located at the specified cursor
|
seeks to the entry located at the specified cursor
|
||||||
string. For details on cursors see
|
string. For details on cursors see
|
||||||
<citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
<citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
|
||||||
|
no entry matching the specified cursor is found the
|
||||||
|
call will seek to the next closest entry (in terms of
|
||||||
|
time) instead. To verify whether the newly selected
|
||||||
|
entry actually matches the cursor use
|
||||||
|
<citerefentry><refentrytitle>sd_journal_test_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
||||||
|
|
||||||
<para>Note that these calls do not actually make any
|
<para>Note that these calls do not actually make any
|
||||||
entry the new current entry, this needs to be done in
|
entry the new current entry, this needs to be done in
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<title>Journal</title>
|
<title>Journal</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
div#divlogs {
|
div#divlogs, div#diventry {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
@ -15,6 +15,12 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
}
|
}
|
||||||
|
div#diventry {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
div#divlogs {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
body {
|
body {
|
||||||
background-color: #ededed;
|
background-color: #ededed;
|
||||||
color: #313739;
|
color: #313739;
|
||||||
|
@ -34,17 +40,41 @@
|
||||||
td.message {
|
td.message {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
td.message > a:link, td.message > a:visited {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #313739;
|
||||||
|
}
|
||||||
td.message-error {
|
td.message-error {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
color: red;
|
color: red;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
td.message-error > a:link, td.message-error > a:visited {
|
||||||
|
text-decoration: none;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
td.message-highlight {
|
td.message-highlight {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
table#tablelogs {
|
td.message-highlight > a:link, td.message-highlight > a:visited {
|
||||||
border-collapse:collapse;
|
text-decoration: none;
|
||||||
|
color: #313739;
|
||||||
|
}
|
||||||
|
td > a:hover, td > a:active {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #c13739;
|
||||||
|
}
|
||||||
|
table#tablelogs, table#tableentry {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
td.field {
|
||||||
|
text-align: right;
|
||||||
|
border-right: 1px dotted lightgrey;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
td.data {
|
||||||
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
@ -65,6 +95,8 @@
|
||||||
<div id="showing"></div>
|
<div id="showing"></div>
|
||||||
|
|
||||||
<div id="divlogs"><table id="tablelogs"></table></div>
|
<div id="divlogs"><table id="tablelogs"></table></div>
|
||||||
|
<a name="entry"></a>
|
||||||
|
<div id="diventry"><table id="tableentry"></table></div>
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<input id="head" type="button" value="|<" onclick="entriesLoadHead();"/>
|
<input id="head" type="button" value="|<" onclick="entriesLoadHead();"/>
|
||||||
|
@ -271,7 +303,7 @@
|
||||||
else if (d.SYSLOG_PID != undefined)
|
else if (d.SYSLOG_PID != undefined)
|
||||||
buf += "[" + d.SYSLOG_PID + "]";
|
buf += "[" + d.SYSLOG_PID + "]";
|
||||||
|
|
||||||
buf += '</td><td class="' + clazz + '">';
|
buf += '</td><td class="' + clazz + '"><a href="#entry" onclick="onMessageClick(\'' + lc + '\');">';
|
||||||
|
|
||||||
if (d.MESSAGE == null)
|
if (d.MESSAGE == null)
|
||||||
buf += "[blob data]";
|
buf += "[blob data]";
|
||||||
|
@ -280,10 +312,10 @@
|
||||||
else
|
else
|
||||||
buf += d.MESSAGE;
|
buf += d.MESSAGE;
|
||||||
|
|
||||||
buf += '</td></tr>';
|
buf += '</a></td></tr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
logs.innerHTML = buf + '</tbody>';
|
logs.innerHTML = '<tbody>' + buf + '</tbody>';
|
||||||
|
|
||||||
if (fc != null)
|
if (fc != null)
|
||||||
first_cursor = fc;
|
first_cursor = fc;
|
||||||
|
@ -293,12 +325,41 @@
|
||||||
|
|
||||||
function entriesMore() {
|
function entriesMore() {
|
||||||
setNEntries(getNEntries() + 10);
|
setNEntries(getNEntries() + 10);
|
||||||
entriesLoad("");
|
entriesLoad(first_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
function entriesLess() {
|
function entriesLess() {
|
||||||
setNEntries(getNEntries() - 10);
|
setNEntries(getNEntries() - 10);
|
||||||
entriesLoad("");
|
entriesLoad(first_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onResultMessageClick(event) {
|
||||||
|
if ((event.currentTarget.readyState != 4) ||
|
||||||
|
(event.currentTarget.status != 200 && event.currentTarget.status != 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var d = JSON.parse(event.currentTarget.responseText);
|
||||||
|
|
||||||
|
document.getElementById("diventry").style.display = "block";
|
||||||
|
|
||||||
|
entry = document.getElementById("tableentry");
|
||||||
|
|
||||||
|
var buf = "";
|
||||||
|
|
||||||
|
for (var key in d){
|
||||||
|
buf += '<tr><td class="field">' + key + '</td><td class="data">' + d[key] + '</td></tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.innerHTML = '<tbody>' + buf + '</tbody>';
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMessageClick(t) {
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.open("GET", "/entries?discrete");
|
||||||
|
request.onreadystatechange = onResultMessageClick;
|
||||||
|
request.setRequestHeader("Accept", "application/json");
|
||||||
|
request.setRequestHeader("Range", "entries=" + t + ":0:1");
|
||||||
|
request.send(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
machineLoad();
|
machineLoad();
|
||||||
|
|
|
@ -49,6 +49,7 @@ typedef struct RequestMeta {
|
||||||
int argument_parse_error;
|
int argument_parse_error;
|
||||||
|
|
||||||
bool follow;
|
bool follow;
|
||||||
|
bool discrete;
|
||||||
} RequestMeta;
|
} RequestMeta;
|
||||||
|
|
||||||
static const char* const mime_types[_OUTPUT_MODE_MAX] = {
|
static const char* const mime_types[_OUTPUT_MODE_MAX] = {
|
||||||
|
@ -205,6 +206,19 @@ static ssize_t request_reader_entries(
|
||||||
return MHD_CONTENT_READER_END_OF_STREAM;
|
return MHD_CONTENT_READER_END_OF_STREAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m->discrete) {
|
||||||
|
assert(m->cursor);
|
||||||
|
|
||||||
|
r = sd_journal_test_cursor(m->journal, m->cursor);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error("Failed to test cursor: %s", strerror(-r));
|
||||||
|
return MHD_CONTENT_READER_END_WITH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == 0)
|
||||||
|
return MHD_CONTENT_READER_END_OF_STREAM;
|
||||||
|
}
|
||||||
|
|
||||||
pos -= m->size;
|
pos -= m->size;
|
||||||
m->delta += m->size;
|
m->delta += m->size;
|
||||||
|
|
||||||
|
@ -380,6 +394,22 @@ static int request_parse_arguments_iterator(
|
||||||
return MHD_YES;
|
return MHD_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (streq(key, "discrete")) {
|
||||||
|
if (isempty(value)) {
|
||||||
|
m->discrete = true;
|
||||||
|
return MHD_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = parse_boolean(value);
|
||||||
|
if (r < 0) {
|
||||||
|
m->argument_parse_error = r;
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
m->discrete = r;
|
||||||
|
return MHD_YES;
|
||||||
|
}
|
||||||
|
|
||||||
p = strjoin(key, "=", strempty(value), NULL);
|
p = strjoin(key, "=", strempty(value), NULL);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
m->argument_parse_error = log_oom();
|
m->argument_parse_error = log_oom();
|
||||||
|
@ -436,6 +466,14 @@ static int request_handler_entries(
|
||||||
if (request_parse_arguments(m, connection) < 0)
|
if (request_parse_arguments(m, connection) < 0)
|
||||||
return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments.\n");
|
return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments.\n");
|
||||||
|
|
||||||
|
if (m->discrete) {
|
||||||
|
if (!m->cursor)
|
||||||
|
return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification.\n");
|
||||||
|
|
||||||
|
m->n_entries = 1;
|
||||||
|
m->n_entries_set = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (m->cursor)
|
if (m->cursor)
|
||||||
r = sd_journal_seek_cursor(m->journal, m->cursor);
|
r = sd_journal_seek_cursor(m->journal, m->cursor);
|
||||||
else if (m->n_skip >= 0)
|
else if (m->n_skip >= 0)
|
||||||
|
|
|
@ -75,3 +75,8 @@ LIBSYSTEMD_JOURNAL_190 {
|
||||||
global:
|
global:
|
||||||
sd_journal_get_usage;
|
sd_journal_get_usage;
|
||||||
} LIBSYSTEMD_JOURNAL_188;
|
} LIBSYSTEMD_JOURNAL_188;
|
||||||
|
|
||||||
|
LIBSYSTEMD_JOURNAL_195 {
|
||||||
|
global:
|
||||||
|
sd_journal_test_cursor;
|
||||||
|
} LIBSYSTEMD_JOURNAL_190;
|
||||||
|
|
|
@ -951,9 +951,8 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
|
_public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
|
||||||
char *w;
|
char *w, *state;
|
||||||
size_t l;
|
size_t l;
|
||||||
char *state;
|
|
||||||
unsigned long long seqnum, monotonic, realtime, xor_hash;
|
unsigned long long seqnum, monotonic, realtime, xor_hash;
|
||||||
bool
|
bool
|
||||||
seqnum_id_set = false,
|
seqnum_id_set = false,
|
||||||
|
@ -966,7 +965,7 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
|
||||||
|
|
||||||
if (!j)
|
if (!j)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!cursor)
|
if (isempty(cursor))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
FOREACH_WORD_SEPARATOR(w, l, cursor, ";", state) {
|
FOREACH_WORD_SEPARATOR(w, l, cursor, ";", state) {
|
||||||
|
@ -1057,6 +1056,89 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
|
||||||
|
int r;
|
||||||
|
char *w, *state;
|
||||||
|
size_t l;
|
||||||
|
Object *o;
|
||||||
|
|
||||||
|
if (!j)
|
||||||
|
return -EINVAL;
|
||||||
|
if (isempty(cursor))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!j->current_file || j->current_file->current_offset <= 0)
|
||||||
|
return -EADDRNOTAVAIL;
|
||||||
|
|
||||||
|
r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
FOREACH_WORD_SEPARATOR(w, l, cursor, ";", state) {
|
||||||
|
_cleanup_free_ char *item = NULL;
|
||||||
|
sd_id128_t id;
|
||||||
|
unsigned long long ll;
|
||||||
|
int k = 0;
|
||||||
|
|
||||||
|
if (l < 2 || w[1] != '=')
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
item = strndup(w, l);
|
||||||
|
if (!item)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
switch (w[0]) {
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
k = sd_id128_from_string(item+2, &id);
|
||||||
|
if (k < 0)
|
||||||
|
return k;
|
||||||
|
if (!sd_id128_equal(id, j->current_file->header->seqnum_id))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
if (sscanf(item+2, "%llx", &ll) != 1)
|
||||||
|
return -EINVAL;
|
||||||
|
if (ll != le64toh(o->entry.seqnum))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
k = sd_id128_from_string(item+2, &id);
|
||||||
|
if (k < 0)
|
||||||
|
return k;
|
||||||
|
if (!sd_id128_equal(id, o->entry.boot_id))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
if (sscanf(item+2, "%llx", &ll) != 1)
|
||||||
|
return -EINVAL;
|
||||||
|
if (ll != le64toh(o->entry.monotonic))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
if (sscanf(item+2, "%llx", &ll) != 1)
|
||||||
|
return -EINVAL;
|
||||||
|
if (ll != le64toh(o->entry.realtime))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
if (sscanf(item+2, "%llx", &ll) != 1)
|
||||||
|
return -EINVAL;
|
||||||
|
if (ll != le64toh(o->entry.xor_hash))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) {
|
_public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) {
|
||||||
if (!j)
|
if (!j)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -39,7 +39,7 @@ static void verify_contents(sd_journal *j, unsigned skip) {
|
||||||
i = 0;
|
i = 0;
|
||||||
SD_JOURNAL_FOREACH(j) {
|
SD_JOURNAL_FOREACH(j) {
|
||||||
const void *d;
|
const void *d;
|
||||||
char *k;
|
char *k, *c;
|
||||||
size_t l;
|
size_t l;
|
||||||
unsigned u;
|
unsigned u;
|
||||||
|
|
||||||
|
@ -61,6 +61,10 @@ static void verify_contents(sd_journal *j, unsigned skip) {
|
||||||
}
|
}
|
||||||
|
|
||||||
free(k);
|
free(k);
|
||||||
|
|
||||||
|
assert_se(sd_journal_get_cursor(j, &c) >= 0);
|
||||||
|
assert_se(sd_journal_test_cursor(j, c) > 0);
|
||||||
|
free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skip > 0)
|
if (skip > 0)
|
||||||
|
@ -122,17 +126,27 @@ int main(int argc, char *argv[]) {
|
||||||
SD_JOURNAL_FOREACH_BACKWARDS(j) {
|
SD_JOURNAL_FOREACH_BACKWARDS(j) {
|
||||||
const void *d;
|
const void *d;
|
||||||
size_t l;
|
size_t l;
|
||||||
|
char *c;
|
||||||
|
|
||||||
assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0);
|
assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0);
|
||||||
printf("\t%.*s\n", (int) l, (const char*) d);
|
printf("\t%.*s\n", (int) l, (const char*) d);
|
||||||
|
|
||||||
|
assert_se(sd_journal_get_cursor(j, &c) >= 0);
|
||||||
|
assert_se(sd_journal_test_cursor(j, c) > 0);
|
||||||
|
free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
SD_JOURNAL_FOREACH(j) {
|
SD_JOURNAL_FOREACH(j) {
|
||||||
const void *d;
|
const void *d;
|
||||||
size_t l;
|
size_t l;
|
||||||
|
char *c;
|
||||||
|
|
||||||
assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0);
|
assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0);
|
||||||
printf("\t%.*s\n", (int) l, (const char*) d);
|
printf("\t%.*s\n", (int) l, (const char*) d);
|
||||||
|
|
||||||
|
assert_se(sd_journal_get_cursor(j, &c) >= 0);
|
||||||
|
assert_se(sd_journal_test_cursor(j, c) > 0);
|
||||||
|
free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
sd_journal_flush_matches(j);
|
sd_journal_flush_matches(j);
|
||||||
|
|
|
@ -104,6 +104,7 @@ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec);
|
||||||
int sd_journal_seek_cursor(sd_journal *j, const char *cursor);
|
int sd_journal_seek_cursor(sd_journal *j, const char *cursor);
|
||||||
|
|
||||||
int sd_journal_get_cursor(sd_journal *j, char **cursor);
|
int sd_journal_get_cursor(sd_journal *j, char **cursor);
|
||||||
|
int sd_journal_test_cursor(sd_journal *j, const char *cursor);
|
||||||
|
|
||||||
int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to);
|
int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to);
|
||||||
int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, const sd_id128_t boot_id, uint64_t *from, uint64_t *to);
|
int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, const sd_id128_t boot_id, uint64_t *from, uint64_t *to);
|
||||||
|
|
Loading…
Reference in New Issue