sd-journal.c revision d5c4ed623b3b83b8caaf6b26f5b4c8006ff372ac
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering This file is part of systemd.
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering Copyright 2011 Lennart Poettering
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering systemd is free software; you can redistribute it and/or modify it
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering under the terms of the GNU Lesser General Public License as published by
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering (at your option) any later version.
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering systemd is distributed in the hope that it will be useful, but
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering Lesser General Public License for more details.
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering You should have received a copy of the GNU Lesser General Public License
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poetteringstatic void detach_location(sd_journal *j) {
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poetteringstatic void reset_location(sd_journal *j) {
cd34b3c6670df8a3fd49179131fe762b2dd86b01Harald Hoyerstatic void init_location(Location *l, LocationType type, JournalFile *f, Object *o) {
cd34b3c6670df8a3fd49179131fe762b2dd86b01Harald Hoyer assert(type == LOCATION_DISCRETE || type == LOCATION_SEEK);
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poettering l->xor_hash = le64toh(o->entry.xor_hash);
cd34b3c6670df8a3fd49179131fe762b2dd86b01Harald Hoyer l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true;
cbdca8525b4f36297cb9e5cb090a9648763ed1bfLennart Poetteringstatic void set_location(sd_journal *j, LocationType type, JournalFile *f, Object *o, uint64_t offset) {
assert(j);
assert(f);
assert(o);
j->current_file = f;
j->current_field = 0;
b = data;
for (p = b; p < b + size; p++) {
size_t j;
Match *m;
return NULL;
m->type = t;
m->parent = p;
assert(m);
while (m->matches)
if (m->parent)
free(m);
assert(m);
if (m->matches)
match_free(m);
return -EINVAL;
if (!data)
return -EINVAL;
if (size == 0)
return -EINVAL;
if (!j->level0) {
if (!j->level0)
return -ENOMEM;
if (!j->level1) {
if (!j->level1)
return -ENOMEM;
if (add_here)
if (!add_here) {
if (!add_here)
goto fail;
goto fail;
if (!m->data)
goto fail;
detach_location(j);
fail:
if (add_here)
if (j->level1)
if (j->level0)
return -ENOMEM;
Match *m;
assert(j);
if (!j->level0)
if (!j->level1)
return -ENOMEM;
j->level1 = m;
Match *i;
bool enclose = false;
p = NULL;
t = match_make_string(i);
free(p);
return NULL;
free(p);
free(t);
return NULL;
enclose = true;
free(p);
if (enclose) {
free(p);
assert(j);
if (j->level0)
detach_location(j);
uint64_t a, b;
uint64_t a;
assert(l);
if (l->monotonic_set &&
l->realtime_set &&
l->xor_hash_set &&
if (l->seqnum_set &&
if (a < l->seqnum)
if (a > l->seqnum)
if (l->monotonic_set &&
if (a < l->monotonic)
if (a > l->monotonic)
if (l->realtime_set) {
if (a < l->realtime)
if (a > l->realtime)
if (l->xor_hash_set) {
if (a < l->xor_hash)
if (a > l->xor_hash)
static int next_for_match(
sd_journal *j,
Match *m,
JournalFile *f,
Object *n;
assert(j);
assert(m);
assert(f);
Match *i;
Match *i;
bool continue_looking;
if (!m->matches)
np = 0;
continue_looking = false;
if (np == 0)
continue_looking = true;
} while (continue_looking);
if (np == 0)
if (ret)
*ret = n;
if (offset)
static int find_location_for_match(
sd_journal *j,
Match *m,
JournalFile *f,
assert(j);
assert(m);
assert(f);
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
return journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, ret, offset);
r = journal_file_move_to_entry_by_monotonic_for_data(f, dp, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
if (r != -ENOENT)
return journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, ret, offset);
Object *n;
Match *i;
if (np == 0)
if (ret)
*ret = n;
if (offset)
Match *i;
if (!m->matches)
static int find_location_with_matches(
sd_journal *j,
JournalFile *f,
assert(j);
assert(f);
if (!j->level0) {
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
if (r != -ENOENT)
return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset);
static int next_with_matches(
sd_journal *j,
JournalFile *f,
Object *c;
assert(j);
assert(f);
c = *ret;
if (!j->level0)
return next_for_match(j, j->level0, f, direction == DIRECTION_DOWN ? cp+1 : cp-1, direction, ret, offset);
static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) {
Object *c;
assert(j);
assert(f);
if (f->current_offset > 0) {
bool found;
found = k > 0;
found = k < 0;
found = true;
if (found) {
if (ret)
*ret = c;
if (offset)
Object *o;
uint64_t p;
Iterator i;
return -EINVAL;
bool found;
if (!new_file)
found = true;
found = k < 0;
found = k > 0;
if (found) {
new_file = f;
new_offset = p;
if (!new_file)
return -EINVAL;
if (skip == 0) {
skip--;
} while (skip > 0);
Object *o;
return -EINVAL;
if (!cursor)
return -EINVAL;
return -EADDRNOTAVAIL;
r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o);
return -ENOMEM;
char *w, *state;
size_t l;
seqnum_id_set = false,
seqnum_set = false,
boot_id_set = false,
monotonic_set = false,
realtime_set = false,
xor_hash_set = false;
return -EINVAL;
return -EINVAL;
char *item;
return -EINVAL;
if (!item)
return -ENOMEM;
seqnum_id_set = true;
seqnum_set = true;
k = -EINVAL;
boot_id_set = true;
monotonic_set = true;
k = -EINVAL;
realtime_set = true;
k = -EINVAL;
xor_hash_set = true;
k = -EINVAL;
return -EINVAL;
reset_location(j);
if (realtime_set) {
if (xor_hash_set) {
char *w, *state;
size_t l;
Object *o;
return -EINVAL;
return -EINVAL;
return -EADDRNOTAVAIL;
r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o);
unsigned long long ll;
return -EINVAL;
if (!item)
return -ENOMEM;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
reset_location(j);
return -EINVAL;
reset_location(j);
return -EINVAL;
reset_location(j);
return -EINVAL;
reset_location(j);
char *path;
JournalFile *f;
assert(j);
if (!path)
return -ENOMEM;
j->current_invalidate_counter ++;
char *path;
JournalFile *f;
assert(j);
if (!path)
return -ENOMEM;
if (j->current_file == f) {
j->current_field = 0;
if (j->unique_file == f) {
j->unique_offset = 0;
j->current_invalidate_counter ++;
char *path;
DIR *d;
Directory *m;
assert(j);
if (!path)
return -ENOMEM;
return -errno;
closedir(d);
return -ENOMEM;
m->is_root = false;
closedir(d);
free(m);
return -ENOMEM;
j->current_invalidate_counter ++;
} else if (m->is_root) {
closedir(d);
if (r != 0 || !de)
closedir(d);
DIR *d;
Directory *m;
assert(j);
assert(p);
return -EINVAL;
d = opendir(p);
return -errno;
closedir(d);
return -ENOMEM;
m->is_root = true;
if (!m->path) {
closedir(d);
free(m);
return -ENOMEM;
closedir(d);
free(m);
return -ENOMEM;
j->current_invalidate_counter ++;
} else if (!m->is_root) {
closedir(d);
if (r != 0 || !de)
closedir(d);
assert(j);
if (d->wd > 0) {
if (j->inotify_fd >= 0)
if (d->is_root)
free(d);
const char search_paths[] =
assert(j);
add_root_directory(j, p);
assert(j);
if (j->inotify_fd < 0) {
if (j->inotify_fd < 0)
return -errno;
if (!j->directories_by_wd) {
if (!j->directories_by_wd)
return -ENOMEM;
sd_journal *j;
return NULL;
if (path) {
if (!j->path) {
free(j);
return NULL;
if (!j->files) {
free(j);
return NULL;
if (!j->directories_by_path) {
free(j);
return NULL;
if (!j->mmap) {
free(j);
return NULL;
sd_journal *j;
if (!ret)
return -EINVAL;
return -EINVAL;
return -ENOMEM;
r = add_search_paths(j);
goto fail;
*ret = j;
fail:
sd_journal_close(j);
sd_journal *j;
if (!ret)
return -EINVAL;
return -EINVAL;
if (flags != 0)
return -EINVAL;
return -ENOMEM;
goto fail;
*ret = j;
fail:
sd_journal_close(j);
Directory *d;
JournalFile *f;
remove_directory(j, d);
remove_directory(j, d);
if (j->inotify_fd >= 0)
if (j->mmap)
free(j);
Object *o;
JournalFile *f;
return -EINVAL;
if (!ret)
return -EINVAL;
f = j->current_file;
return -EADDRNOTAVAIL;
if (f->current_offset <= 0)
return -EADDRNOTAVAIL;
Object *o;
JournalFile *f;
return -EINVAL;
f = j->current_file;
return -EADDRNOTAVAIL;
if (f->current_offset <= 0)
return -EADDRNOTAVAIL;
if (ret_boot_id)
return -ESTALE;
if (ret)
for (p = field; *p; p++) {
_public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) {
JournalFile *f;
uint64_t i, n;
Object *o;
return -EINVAL;
if (!field)
return -EINVAL;
if (!data)
return -EINVAL;
if (!size)
return -EINVAL;
return -EINVAL;
f = j->current_file;
return -EADDRNOTAVAIL;
if (f->current_offset <= 0)
return -EADDRNOTAVAIL;
n = journal_file_entry_n_items(o);
uint64_t p, l;
size_t t;
return -EBADMSG;
#ifdef HAVE_XZ
return -EBADMSG;
return -EPROTONOSUPPORT;
t = (size_t) l;
if ((uint64_t) t != l)
return -E2BIG;
*size = t;
return -ENOENT;
size_t t;
uint64_t l;
t = (size_t) l;
if ((uint64_t) t != l)
return -E2BIG;
#ifdef HAVE_XZ
return -EBADMSG;
return -EPROTONOSUPPORT;
*size = t;
JournalFile *f;
uint64_t p, n;
Object *o;
return -EINVAL;
if (!data)
return -EINVAL;
if (!size)
return -EINVAL;
f = j->current_file;
return -EADDRNOTAVAIL;
if (f->current_offset <= 0)
return -EADDRNOTAVAIL;
n = journal_file_entry_n_items(o);
if (j->current_field >= n)
return -EBADMSG;
j->current_field ++;
j->current_field = 0;
return -EINVAL;
if (j->inotify_fd >= 0)
return j->inotify_fd;
r = allocate_inotify(j);
if (j->path)
r = add_search_paths(j);
return j->inotify_fd;
Directory *d;
assert(j);
assert(e);
r = remove_directory(j, d);
} else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && sd_id128_from_string(e->name, &id) >= 0) {
assert(j);
bool got_something = false;
return -EINVAL;
struct inotify_event *e;
ssize_t l;
return -errno;
got_something = true;
process_inotify_event(j, e);
l -= step;
return determine_change(j);
assert(j);
if (j->inotify_fd < 0) {
r = sd_journal_get_fd(j);
return determine_change(j);
} while (r == -EINTR);
return sd_journal_process(j);
Iterator i;
JournalFile *f;
bool first = true;
return -EINVAL;
return -EINVAL;
if (r == -ENOENT)
if (first) {
if (from)
if (to)
*to = t;
first = false;
if (from)
if (to)
_public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) {
Iterator i;
JournalFile *f;
bool first = true;
return -EINVAL;
return -EINVAL;
if (r == -ENOENT)
if (first) {
if (from)
if (to)
*to = t;
first = false;
if (from)
if (to)
Iterator i;
JournalFile *f;
bool newline = false;
assert(j);
if (newline)
newline = true;
Iterator i;
JournalFile *f;
return -EINVAL;
if (!bytes)
return -EINVAL;
return -errno;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -ENOMEM;
j->unique_field = f;
j->unique_offset = 0;
Object *o;
size_t k;
return -EINVAL;
if (!data)
return -EINVAL;
return -EINVAL;
if (!j->unique_field)
return -EINVAL;
if (!j->unique_file) {
if (!j->unique_file)
j->unique_offset = 0;
Iterator i;
const void *odata;
bool found;
if (j->unique_offset == 0) {
if (j->unique_offset == 0) {
JournalFile *n;
j->unique_file = n;
return -EBADMSG;
found = false;
found = true;
if (found)
j->unique_offset = 0;