sd-journal.c revision 7827b1a10f4dfe2c6771b515f28f7ae22e0ae039
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2011 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringstatic void reset_location(sd_journal *j) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void init_location(Location *l, JournalFile *f, Object *o) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering l->realtime = le64toh(o->entry.realtime);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering l->monotonic = le64toh(o->entry.monotonic);
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poettering l->xor_hash = le64toh(o->entry.xor_hash);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void set_location(sd_journal *j, JournalFile *f, Object *o, uint64_t offset) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering init_location(&j->current_location, f, o);
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poetteringstatic int match_is_valid(const void *data, size_t size) {
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering const char *b, *p;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering for (p = b; p < b + size; p++) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering if (*p == '=')
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering if (*p == '_')
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poetteringstatic bool same_field(const void *_a, size_t s, const void *_b, size_t t) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (j = 0; j < s && j < t; j++) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (a[j] != b[j])
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (a[j] == '=')
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic Match *match_new(Match *p, MatchType t) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_PREPEND(Match, matches, p->matches, m);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering LIST_REMOVE(Match, matches, m->parent->matches, m);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poetteringstatic void match_free_if_empty(Match *m) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen_public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) {
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering /* level 0: OR term
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering * level 1: AND terms
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen * level 2: OR terms
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering * level 3: concrete matches */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering j->level0 = match_new(NULL, MATCH_OR_TERM);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering j->level1 = match_new(j->level0, MATCH_AND_TERM);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(j->level0->type == MATCH_OR_TERM);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(j->level1->type == MATCH_AND_TERM);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering LIST_FOREACH(matches, l2, j->level1->matches) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Exactly the same match already? Then ignore
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * this addition */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering /* Same field? Then let's add this to this OR term */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (same_field(data, size, l3->data, l3->size)) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering add_here = match_new(j->level1, MATCH_OR_TERM);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering_public_ int sd_journal_add_disjunction(sd_journal *j) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering m = match_new(j->level0, MATCH_AND_TERM);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic char *match_make_string(Match *m) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringchar *journal_make_match_string(sd_journal *j) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering_public_ void sd_journal_flush_matches(sd_journal *j) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int compare_order(JournalFile *af, Object *ao,
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering /* We operate on two different files here, hence we can access
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering * two objects at the same time, which we normally can't.
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * If contents and timestamps match, these entries are
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * identical, even if the seqnum does not match */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id) &&
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering ao->entry.monotonic == bo->entry.monotonic &&
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering ao->entry.realtime == bo->entry.realtime &&
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering ao->entry.xor_hash == bo->entry.xor_hash)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* If this is from the same seqnum source, compare
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* Wow! This is weird, different data but the same
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * seqnums? Something is borked, but let's make the
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * best of it and compare by time. */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id)) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* If the boot id matches compare monotonic time */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* Otherwise compare UTC time */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* Finally, compare by contents */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int compare_with_location(JournalFile *af, Object *ao, Location *l) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering sd_id128_equal(ao->entry.boot_id, l->boot_id) &&
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering le64toh(ao->entry.realtime) == l->realtime &&
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering le64toh(ao->entry.xor_hash) == l->xor_hash)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering sd_id128_equal(af->header->seqnum_id, l->seqnum_id)) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering sd_id128_equal(ao->entry.boot_id, l->boot_id)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return journal_file_move_to_entry_by_offset_for_data(f, dp, after_offset, direction, ret, offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Find the earliest match beyond after_offset */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = next_for_match(j, i, f, after_offset, direction, NULL, &cp);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (r > 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Always jump to the next matching entry and repeat
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * this until we fine and offset that matches for all
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = next_for_match(j, i, f, limit, direction, NULL, &cp);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if ((direction == DIRECTION_DOWN ? cp >= after_offset : cp <= after_offset) &&
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering (np == 0 || (direction == DIRECTION_DOWN ? cp > np : np < cp))) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* FIXME: missing: find by monotonic */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (j->current_location.type == LOCATION_HEAD)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_DOWN, ret, offset);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (j->current_location.type == LOCATION_TAIL)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_UP, ret, offset);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, ret, offset);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = journal_file_move_to_entry_by_monotonic_for_data(f, dp, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering return journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, ret, offset);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering return journal_file_next_entry_for_data(f, NULL, 0, dp, direction, ret, offset);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Find the earliest match */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = find_location_for_match(j, i, f, direction, NULL, &cp);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (r > 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* First jump to the last match, and then find the
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers * next one where all matches match */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = find_location_for_match(j, i, f, direction, NULL, &cp);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (np == 0 || (direction == DIRECTION_DOWN ? np < cp : np > cp))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return next_for_match(j, m, f, np, direction, ret, offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* No matches is simple */
8c841f21f5042b11acc91cc1b039cb162cbbe8f4Djalal Harouni if (j->current_location.type == LOCATION_HEAD)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, ret, offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (j->current_location.type == LOCATION_TAIL)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return journal_file_next_entry(f, NULL, 0, DIRECTION_UP, ret, offset);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return journal_file_next_entry(f, NULL, 0, direction, ret, offset);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return find_location_for_match(j, j->level0, f, direction, ret, offset);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* No matches is easy. We simple advance the file
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * pointer by one. */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return journal_file_next_entry(f, c, cp, direction, ret, offset);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* If we have a match then we look for the next matching entry
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering * with an offset at least one step larger */
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering return next_for_match(j, j->level0, f, direction == DIRECTION_DOWN ? cp+1 : cp-1, direction, ret, offset);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, cp, &c);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = next_with_matches(j, f, direction, &c, &cp);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = find_location_with_matches(j, f, direction, &c, &cp);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* OK, we found the spot, now let's advance until to an entry
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * that is actually different from what we were previously
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * looking at. This is necessary to handle entries which exist
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * in two (or more) journal files, and which shall all be
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * suppressed but one. */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (j->current_location.type == LOCATION_DISCRETE) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering k = compare_with_location(f, c, &j->current_location);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = next_with_matches(j, f, direction, &c, &cp);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poetteringstatic int real_journal_next(sd_journal *j, direction_t direction) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = next_beyond_location(j, f, direction, &o, &p);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering log_debug("Can't iterate through %s, ignoring: %s", f->path, strerror(-r));
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering } else if (r == 0)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering k = compare_order(f, o, new_current, new_entry);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering set_location(j, new_current, new_entry, new_offset);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering_public_ int sd_journal_next(sd_journal *j) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return real_journal_next(j, DIRECTION_DOWN);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering_public_ int sd_journal_previous(sd_journal *j) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return real_journal_next(j, DIRECTION_UP);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringstatic int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t skip) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering /* If this is not a discrete skip, then at least
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering * resolve the current location */
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (j->current_location.type != LOCATION_DISCRETE)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering } while (skip > 0);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering_public_ int sd_journal_next_skip(sd_journal *j, uint64_t skip) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return real_journal_next_skip(j, DIRECTION_DOWN, skip);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering_public_ int sd_journal_previous_skip(sd_journal *j, uint64_t skip) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return real_journal_next_skip(j, DIRECTION_UP, skip);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering_public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (!j->current_file || j->current_file->current_offset <= 0)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering sd_id128_to_string(j->current_file->header->seqnum_id, sid);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering sd_id128_to_string(o->entry.boot_id, bid);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering "s=%s;i=%llx;b=%s;m=%llx;t=%llx;x=%llx;p=%s",
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering sid, (unsigned long long) le64toh(o->entry.seqnum),
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering bid, (unsigned long long) le64toh(o->entry.monotonic),
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering (unsigned long long) le64toh(o->entry.realtime),
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering (unsigned long long) le64toh(o->entry.xor_hash),
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering path_get_file_name(j->current_file->path)) < 0)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering_public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering unsigned long long seqnum, monotonic, realtime, xor_hash;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering FOREACH_WORD_SEPARATOR(w, l, cursor, ";", state) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering switch (w[0]) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering k = sd_id128_from_string(w+2, &seqnum_id);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (sscanf(w+2, "%llx", &monotonic) != 1)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering j->current_location.type = LOCATION_DISCRETE;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering j->current_location.realtime = (uint64_t) realtime;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering j->current_location.seqnum = (uint64_t) seqnum;
2723b3b51d409340558e46e37e90525d4f880fe1Lennart Poettering j->current_location.seqnum_id = seqnum_id;
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering j->current_location.monotonic = (uint64_t) monotonic;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering j->current_location.monotonic_set = true;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering j->current_location.xor_hash = (uint64_t) xor_hash;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering_public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering j->current_location.type = LOCATION_DISCRETE;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering j->current_location.monotonic_set = true;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering_public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering j->current_location.type = LOCATION_DISCRETE;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering_public_ int sd_journal_seek_head(sd_journal *j) {
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering j->current_location.type = LOCATION_HEAD;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering_public_ int sd_journal_seek_tail(sd_journal *j) {
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering j->current_location.type = LOCATION_TAIL;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int add_file(sd_journal *j, const char *prefix, const char *filename) {
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering if ((j->flags & SD_JOURNAL_SYSTEM_ONLY) &&
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering (startswith(filename, "system@") && endswith(filename, ".journal"))))
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering path = strjoin(prefix, "/", filename, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering log_debug("Too many open journal files, not adding %s, ignoring.", path);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering r = journal_file_open(path, O_RDONLY, 0, NULL, NULL, &f);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering /* journal_file_dump(f); */
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering log_debug("File %s got added.", f->path);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poetteringstatic int remove_file(sd_journal *j, const char *prefix, const char *filename) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering path = strjoin(prefix, "/", filename, NULL);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering log_debug("File %s got removed.", f->path);
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poetteringstatic int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering (sd_id128_from_string(dirname, &id) < 0 ||
2723b3b51d409340558e46e37e90525d4f880fe1Lennart Poettering path = strjoin(prefix, "/", dirname, NULL);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering log_debug("Failed to open %s: %m", path);
813c65c34beae2eed1f93d9317f97d7e806389f5Lennart Poettering m = hashmap_get(j->directories_by_path, path);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
c7b7d4493aa03e9ef5fb1e670b8969a48aa494ddLennart Poettering log_debug("Directory %s got added.", m->path);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering } else if (m->is_root) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering m->wd = inotify_add_watch(j->inotify_fd, m->path,
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (r != 0 || !de)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (dirent_is_file_with_suffix(de, ".journal")) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r));
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poetteringstatic int add_root_directory(sd_journal *j, const char *p) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering m = hashmap_get(j->directories_by_path, p);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_debug("Root directory %s got added.", m->path);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering } else if (!m->is_root) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering m->wd = inotify_add_watch(j->inotify_fd, m->path,
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (r != 0 || !de)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (dirent_is_file_with_suffix(de, ".journal")) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r));
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering } else if ((de->d_type == DT_DIR || de->d_type == DT_LNK || de->d_type == DT_UNKNOWN) &&
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering sd_id128_from_string(de->d_name, &id) >= 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = add_directory(j, m->path, de->d_name);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_debug("Failed to add directory %s/%s: %s", m->path, de->d_name, strerror(-r));
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poetteringstatic int remove_directory(sd_journal *j, Directory *d) {
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering if (d->wd > 0) {
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering hashmap_remove(j->directories_by_wd, INT_TO_PTR(d->wd));
2723b3b51d409340558e46e37e90525d4f880fe1Lennart Poettering hashmap_remove(j->directories_by_path, d->path);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering log_debug("Root directory %s got removed.", d->path);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering log_debug("Directory %s got removed.", d->path);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poetteringstatic int add_search_paths(sd_journal *j) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering const char *p;
2723b3b51d409340558e46e37e90525d4f880fe1Lennart Poettering /* We ignore most errors here, since the idea is to only open
2723b3b51d409340558e46e37e90525d4f880fe1Lennart Poettering * what's actually accessible, and ignore the rest. */
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poetteringstatic int allocate_inotify(sd_journal *j) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering j->directories_by_wd = hashmap_new(trivial_hash_func, trivial_compare_func);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poetteringstatic sd_journal *journal_new(int flags, const char *path) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering j->files = hashmap_new(string_hash_func, string_compare_func);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering j->directories_by_path = hashmap_new(string_hash_func, string_compare_func);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering_public_ int sd_journal_open(sd_journal **ret, int flags) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering_public_ void sd_journal_close(sd_journal *j) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering while ((f = hashmap_steal_first(j->files)))
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering while ((d = hashmap_first(j->directories_by_path)))
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering while ((d = hashmap_first(j->directories_by_wd)))
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering_public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) {
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering_public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id) {
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (!sd_id128_equal(id, o->entry.boot_id))
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringstatic bool field_is_valid(const char *field) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering const char *p;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering for (p = field; *p; p++) {
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering if (*p == '_')
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering_public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering for (i = 0; i < n; i++) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering p = le64toh(o->entry.items[i].object_offset);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering l = le64toh(o->object.size) - offsetof(Object, data.payload);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (o->object.flags & OBJECT_COMPRESSED) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (uncompress_startswith(o->data.payload, l,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering &f->compress_buffer, &f->compress_buffer_size,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering &f->compress_buffer, &f->compress_buffer_size, &rsize))
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering memcmp(o->data.payload, field, field_length) == 0 &&
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering_public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poettering p = le64toh(o->entry.items[j->current_field].object_offset);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering le_hash = o->entry.items[j->current_field].hash;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering l = le64toh(o->object.size) - offsetof(Object, data.payload);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* We can't read objects larger than 4G on a 32bit machine */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (o->object.flags & OBJECT_COMPRESSED) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (!uncompress_blob(o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize))
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering_public_ void sd_journal_restart_data(sd_journal *j) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering_public_ int sd_journal_get_fd(sd_journal *j) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* Iterate through all dirs again, to add them to the
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringstatic void process_inotify_event(sd_journal *j, struct inotify_event *e) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* Is this a subdirectory we watch? */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering d = hashmap_get(j->directories_by_wd, INT_TO_PTR(e->wd));
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (!(e->mask & IN_ISDIR) && e->len > 0 && endswith(e->name, ".journal")) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* Event for a journal file */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_debug("Failed to add file %s/%s: %s", d->path, e->name, strerror(-r));
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering } else if (e->mask & (IN_DELETE|IN_UNMOUNT)) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_debug("Failed to remove file %s/%s: %s", d->path, e->name, strerror(-r));
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* Event for a subdirectory */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_debug("Failed to remove directory %s: %s", d->path, strerror(-r));
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering } else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && sd_id128_from_string(e->name, &id) >= 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* Event for root directory */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_debug("Failed to add directory %s/%s: %s", d->path, e->name, strerror(-r));
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringstatic int determine_change(sd_journal *j) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering b = j->current_invalidate_counter != j->last_invalidate_counter;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering j->last_invalidate_counter = j->current_invalidate_counter;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return b ? SD_JOURNAL_INVALIDATE : SD_JOURNAL_APPEND;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering_public_ int sd_journal_process(sd_journal *j) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering uint8_t buffer[sizeof(struct inotify_event) + FILENAME_MAX] _alignas_(struct inotify_event);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering l = read(j->inotify_fd, buffer, sizeof(buffer));
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return got_something ? determine_change(j) : SD_JOURNAL_NOP;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering while (l > 0) {
7079cfeffb6d520f20ddff53fd78467e72e6cc94Lennart Poettering step = sizeof(struct inotify_event) + e->len;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering e = (struct inotify_event*) ((uint8_t*) e + step);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering_public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* This is the first invocation, hence create the
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * inotify watch */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* The journal might have changed since the context
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * object was created and we weren't watching before,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * hence don't wait for anything, and return
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * immediately. */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering r = fd_wait_for_event(j->inotify_fd, POLLIN, timeout_usec);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering } while (r == -EINTR);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering_public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) {
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering r = journal_file_get_cutoff_realtime_usec(f, &fr, &t);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering_public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) {
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering r = journal_file_get_cutoff_monotonic_usec(f, boot_id, &fr, &t);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poetteringvoid journal_print_header(sd_journal *j) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering/* _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { */
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering/* return -EINVAL; */
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering/* if (!field) */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering/* return -EINVAL; */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering/* return -ENOTSUP; */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering/* _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) { */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering/* return -EINVAL; */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering/* return -EINVAL; */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering/* return -EINVAL; */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering/* return -ENOTSUP; */
b5b38b41c37dbe1a117af9bf99e94b58ac91239aLennart Poettering/* _public_ void sd_journal_restart_unique(sd_journal *j) { */