X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjournal%2Fsd-journal.c;h=831ab6b4e9b28446812f05e02faf74a40519f096;hp=1c91f007b79bff96f56ed47d891190e5fd751197;hb=581483bf59ea62147739e71dd2216477be03411c;hpb=bf807d4dbf27c783db8dfd7f4eca321ae4be5b00 diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 1c91f007b..831ab6b4e 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -41,6 +41,7 @@ #include "missing.h" #include "catalog.h" #include "replace-var.h" +#include "fileio.h" #define JOURNAL_FILES_MAX 1024 @@ -216,19 +217,14 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) Match *l3, *l4, *add_here = NULL, *m; le64_t le_hash; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - - if (!data) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(data, -EINVAL); if (size == 0) size = strlen(data); - if (!match_is_valid(data, size)) - return -EINVAL; + assert_return(match_is_valid(data, size), -EINVAL); /* level 0: AND term * level 1: OR terms @@ -314,10 +310,8 @@ fail: } _public_ int sd_journal_add_conjunction(sd_journal *j) { - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); if (!j->level0) return 0; @@ -335,10 +329,8 @@ _public_ int sd_journal_add_conjunction(sd_journal *j) { } _public_ int sd_journal_add_disjunction(sd_journal *j) { - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); if (!j->level0) return 0; @@ -472,7 +464,7 @@ static int compare_entry_order(JournalFile *af, Object *_ao, if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id)) { - /* If the boot id matches compare monotonic time */ + /* If the boot id matches, compare monotonic time */ a = le64toh(ao->entry.monotonic); b = le64toh(bo->entry.monotonic); @@ -482,7 +474,7 @@ static int compare_entry_order(JournalFile *af, Object *_ao, return 1; } - /* Otherwise compare UTC time */ + /* Otherwise, compare UTC time */ a = le64toh(ao->entry.realtime); b = le64toh(bo->entry.realtime); @@ -884,10 +876,8 @@ static int real_journal_next(sd_journal *j, direction_t direction) { Iterator i; int r; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); HASHMAP_FOREACH(f, j->files, i) { bool found; @@ -938,10 +928,8 @@ _public_ int sd_journal_previous(sd_journal *j) { static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t skip) { int c = 0, r; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); if (skip == 0) { /* If this is not a discrete skip, then at least @@ -980,12 +968,9 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) { int r; char bid[33], sid[33]; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!cursor) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(cursor, -EINVAL); if (!j->current_file || j->current_file->current_offset <= 0) return -EADDRNOTAVAIL; @@ -1021,12 +1006,9 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) { xor_hash_set = false; sd_id128_t seqnum_id, boot_id; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (isempty(cursor)) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!isempty(cursor), -EINVAL); FOREACH_WORD_SEPARATOR(w, l, cursor, ";", state) { char *item; @@ -1122,12 +1104,9 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) { size_t l; Object *o; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (isempty(cursor)) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!isempty(cursor), -EINVAL); if (!j->current_file || j->current_file->current_offset <= 0) return -EADDRNOTAVAIL; @@ -1202,10 +1181,8 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) { _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) { - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); reset_location(j); j->current_location.type = LOCATION_SEEK; @@ -1217,10 +1194,8 @@ _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, u } _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) { - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); reset_location(j); j->current_location.type = LOCATION_SEEK; @@ -1231,10 +1206,8 @@ _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) { } _public_ int sd_journal_seek_head(sd_journal *j) { - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); reset_location(j); j->current_location.type = LOCATION_HEAD; @@ -1243,10 +1216,8 @@ _public_ int sd_journal_seek_head(sd_journal *j) { } _public_ int sd_journal_seek_tail(sd_journal *j) { - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); reset_location(j); j->current_location.type = LOCATION_TAIL; @@ -1310,7 +1281,7 @@ static bool file_type_wanted(int flags, const char *filename) { } static int add_any_file(sd_journal *j, const char *path) { - JournalFile *f; + JournalFile *f = NULL; int r; assert(j); @@ -1471,10 +1442,16 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname) for (;;) { struct dirent *de; - union dirent_storage buf; - r = readdir_r(d, &buf.de, &de); - if (r != 0 || !de) + errno = 0; + de = readdir(d); + if (!de && errno != 0) { + r = -errno; + log_debug("Failed to read directory %s: %s", + m->path, strerror(errno)); + return r; + } + if (!de) break; if (dirent_is_file_with_suffix(de, ".journal") || @@ -1507,6 +1484,9 @@ static int add_root_directory(sd_journal *j, const char *p) { !path_startswith(p, "/run")) return -EINVAL; + if (j->prefix) + p = strappenda(j->prefix, p); + d = opendir(p); if (!d) return -errno; @@ -1552,11 +1532,17 @@ static int add_root_directory(sd_journal *j, const char *p) { for (;;) { struct dirent *de; - union dirent_storage buf; sd_id128_t id; - r = readdir_r(d, &buf.de, &de); - if (r != 0 || !de) + errno = 0; + de = readdir(d); + if (!de && errno != 0) { + r = -errno; + log_debug("Failed to read directory %s: %s", + m->path, strerror(errno)); + return r; + } + if (!de) break; if (dirent_is_file_with_suffix(de, ".journal") || @@ -1642,8 +1628,8 @@ static int add_current_paths(sd_journal *j) { * treat them as fatal. */ HASHMAP_FOREACH(f, j->files, i) { - int r; _cleanup_free_ char *dir; + int r; dir = dirname_malloc(f->path); if (!dir) @@ -1713,14 +1699,8 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) { sd_journal *j; int r; - if (!ret) - return -EINVAL; - - if (flags & ~(SD_JOURNAL_LOCAL_ONLY| - SD_JOURNAL_RUNTIME_ONLY| - SD_JOURNAL_SYSTEM| - SD_JOURNAL_CURRENT_USER)) - return -EINVAL; + assert_return(ret, -EINVAL); + assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_RUNTIME_ONLY|SD_JOURNAL_SYSTEM|SD_JOURNAL_CURRENT_USER)) == 0, -EINVAL); j = journal_new(flags, NULL); if (!j) @@ -1739,18 +1719,55 @@ fail: return r; } -_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) { +_public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) { + _cleanup_free_ char *root = NULL, *class = NULL; sd_journal *j; + char *p; int r; - if (!ret) - return -EINVAL; + assert_return(machine, -EINVAL); + assert_return(ret, -EINVAL); + assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM)) == 0, -EINVAL); + assert_return(filename_is_safe(machine), -EINVAL); - if (!path) - return -EINVAL; + p = strappenda("/run/systemd/machines/", machine); + r = parse_env_file(p, NEWLINE, "ROOT", &root, "CLASS", &class, NULL); + if (r == -ENOENT) + return -EHOSTDOWN; + if (r < 0) + return r; + if (!root) + return -ENODATA; - if (flags != 0) - return -EINVAL; + if (!streq_ptr(class, "container")) + return -EIO; + + j = journal_new(flags, NULL); + if (!j) + return -ENOMEM; + + j->prefix = root; + root = NULL; + + r = add_search_paths(j); + if (r < 0) + goto fail; + + *ret = j; + return 0; + +fail: + sd_journal_close(j); + return r; +} + +_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) { + sd_journal *j; + int r; + + assert_return(ret, -EINVAL); + assert_return(path, -EINVAL); + assert_return(flags == 0, -EINVAL); j = journal_new(flags, path); if (!j) @@ -1776,11 +1793,8 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla const char **path; int r; - if (!ret) - return -EINVAL; - - if (flags != 0) - return -EINVAL; + assert_return(ret, -EINVAL); + assert_return(flags == 0, -EINVAL); j = journal_new(flags, NULL); if (!j) @@ -1837,6 +1851,7 @@ _public_ void sd_journal_close(sd_journal *j) { } free(j->path); + free(j->prefix); free(j->unique_field); set_free(j->errors); free(j); @@ -1847,12 +1862,9 @@ _public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) { JournalFile *f; int r; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!ret) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(ret, -EINVAL); f = j->current_file; if (!f) @@ -1875,10 +1887,8 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12 int r; sd_id128_t id; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); f = j->current_file; if (!f) @@ -1943,19 +1953,12 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** int r; Object *o; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!field) - return -EINVAL; - if (!data) - return -EINVAL; - if (!size) - return -EINVAL; - - if (!field_is_valid(field)) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(field, -EINVAL); + assert_return(data, -EINVAL); + assert_return(size, -EINVAL); + assert_return(field_is_valid(field), -EINVAL); f = j->current_file; if (!f) @@ -2071,14 +2074,10 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t int r; Object *o; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!data) - return -EINVAL; - if (!size) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(data, -EINVAL); + assert_return(size, -EINVAL); f = j->current_file; if (!f) @@ -2123,10 +2122,8 @@ _public_ void sd_journal_restart_data(sd_journal *j) { _public_ int sd_journal_get_fd(sd_journal *j) { int r; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); if (j->inotify_fd >= 0) return j->inotify_fd; @@ -2152,10 +2149,8 @@ _public_ int sd_journal_get_fd(sd_journal *j) { _public_ int sd_journal_get_events(sd_journal *j) { int fd; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); fd = sd_journal_get_fd(j); if (fd < 0) @@ -2167,12 +2162,9 @@ _public_ int sd_journal_get_events(sd_journal *j) { _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) { int fd; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!timeout_usec) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(timeout_usec, -EINVAL); fd = sd_journal_get_fd(j); if (fd < 0) @@ -2269,10 +2261,8 @@ _public_ int sd_journal_process(sd_journal *j) { uint8_t buffer[sizeof(struct inotify_event) + FILENAME_MAX] _alignas_(struct inotify_event); bool got_something = false; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); j->last_process_usec = now(CLOCK_MONOTONIC); @@ -2311,10 +2301,8 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { int r; uint64_t t; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); if (j->inotify_fd < 0) { @@ -2359,16 +2347,13 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, Iterator i; JournalFile *f; bool first = true; + uint64_t fmin = 0, tmax = 0; int r; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!from && !to) - return -EINVAL; - if (from == to) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(from || to, -EINVAL); + assert_return(from != to, -EINVAL); HASHMAP_FOREACH(f, j->files, i) { usec_t fr, t; @@ -2382,19 +2367,20 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, continue; if (first) { - if (from) - *from = fr; - if (to) - *to = t; + fmin = fr; + tmax = t; first = false; } else { - if (from) - *from = MIN(fr, *from); - if (to) - *to = MAX(t, *to); + fmin = MIN(fr, fmin); + tmax = MAX(t, tmax); } } + if (from) + *from = fmin; + if (to) + *to = tmax; + return first ? 0 : 1; } @@ -2404,14 +2390,10 @@ _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot bool first = true; int r; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!from && !to) - return -EINVAL; - if (from == to) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(from || to, -EINVAL); + assert_return(from != to, -EINVAL); HASHMAP_FOREACH(f, j->files, i) { usec_t fr, t; @@ -2463,12 +2445,9 @@ _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) { JournalFile *f; uint64_t sum = 0; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!bytes) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(bytes, -EINVAL); HASHMAP_FOREACH(f, j->files, i) { struct stat st; @@ -2486,14 +2465,10 @@ _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) { _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { char *f; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (isempty(field)) - return -EINVAL; - if (!field_is_valid(field)) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!isempty(field), -EINVAL); + assert_return(field_is_valid(field), -EINVAL); f = strdup(field); if (!f) @@ -2508,20 +2483,13 @@ _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { } _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) { - Object *o; size_t k; - int r; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!data) - return -EINVAL; - if (!l) - return -EINVAL; - if (!j->unique_field) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(data, -EINVAL); + assert_return(l, -EINVAL); + assert_return(j->unique_field, -EINVAL); k = strlen(j->unique_field); @@ -2535,9 +2503,11 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_ for (;;) { JournalFile *of; Iterator i; + Object *o; const void *odata; size_t ol; bool found; + int r; /* Proceed to next data object in the field's linked list */ if (j->unique_offset == 0) { @@ -2574,8 +2544,16 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_ return r; /* Let's do the type check by hand, since we used 0 context above. */ - if (o->object.type != OBJECT_DATA) + if (o->object.type != OBJECT_DATA) { + log_error("%s:offset " OFSfmt ": object has type %d, expected %d", + j->unique_file->path, j->unique_offset, + o->object.type, OBJECT_DATA); return -EBADMSG; + } + + r = journal_file_object_keep(j->unique_file, o, j->unique_offset); + if (r < 0) + return r; r = return_data(j, j->unique_file, o, &odata, &ol); if (r < 0) @@ -2609,6 +2587,10 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_ if (found) continue; + r = journal_file_object_release(j->unique_file, o, j->unique_offset); + if (r < 0) + return r; + r = return_data(j, j->unique_file, o, data, l); if (r < 0) return r; @@ -2626,10 +2608,8 @@ _public_ void sd_journal_restart_unique(sd_journal *j) { } _public_ int sd_journal_reliable_fd(sd_journal *j) { - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); return !j->on_network; } @@ -2661,12 +2641,9 @@ _public_ int sd_journal_get_catalog(sd_journal *j, char **ret) { char *t; int r; - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!ret) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(ret, -EINVAL); r = sd_journal_get_data(j, "MESSAGE_ID", &data, &size); if (r < 0) @@ -2693,29 +2670,23 @@ _public_ int sd_journal_get_catalog(sd_journal *j, char **ret) { } _public_ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret) { - if (!ret) - return -EINVAL; + assert_return(ret, -EINVAL); return catalog_get(CATALOG_DATABASE, id, ret); } _public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) { - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); j->data_threshold = sz; return 0; } _public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) { - if (!j) - return -EINVAL; - if (journal_pid_changed(j)) - return -ECHILD; - if (!sz) - return -EINVAL; + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(sz, -EINVAL); *sz = j->data_threshold; return 0;