diff --git a/src/journal/test-journal-flush.c b/src/journal/test-journal-flush.c index 421cae06b2a..c734aa02ca4 100644 --- a/src/journal/test-journal-flush.c +++ b/src/journal/test-journal-flush.c @@ -58,8 +58,7 @@ static void test_journal_flush(int argc, char *argv[]) { assert_se(r >= 0 || IN_SET(r, -EBADMSG, /* corrupted file */ -EPROTONOSUPPORT, /* unsupported compression */ - -EIO, /* file rotated */ - -EADDRNOTAVAIL)); /* corrupted file */ + -EIO)); /* file rotated */ if (++n >= 10000) break; diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 7dbbd4889c4..02e9b9a6742 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -395,6 +395,9 @@ static bool warn_wrong_flags(const JournalFile *f, bool compatible) { const char *type = compatible ? "compatible" : "incompatible"; uint32_t flags; + assert(f); + assert(f->header); + flags = le32toh(compatible ? f->header->compatible_flags : f->header->incompatible_flags); if (flags & ~supported) { @@ -640,6 +643,10 @@ static int journal_file_move_to( assert(f); assert(ret); + /* This function may clear, overwrite, or alter previously cached entries. After this function has + * been called, all objects except for one obtained by this function are invalidated and must be + * re-read before use. */ + if (size <= 0) return -EINVAL; @@ -724,6 +731,7 @@ static int check_object_header(JournalFile *f, Object *o, ObjectType type, uint6 /* Lightweight object checks. We want this to be fast, so that we won't * slowdown every journal_file_move_to_object() call too much. */ static int check_object(JournalFile *f, Object *o, uint64_t offset) { + assert(f); assert(o); switch (o->object.type) { @@ -874,6 +882,10 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset assert(f); + /* Even if this function fails, it may clear, overwrite, or alter previously cached entries. After + * this function has been called, all objects except for one obtained by this function are + * invalidated and must be re-read before use.. */ + /* Objects may only be located at multiple of 64 bit */ if (!VALID64(offset)) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), @@ -996,7 +1008,7 @@ int journal_file_append_object( JournalFile *f, ObjectType type, uint64_t size, - Object **ret, + Object **ret_object, uint64_t *ret_offset) { int r; @@ -1032,8 +1044,8 @@ int journal_file_append_object( f->header->tail_object_offset = htole64(p); f->header->n_objects = htole64(le64toh(f->header->n_objects) + 1); - if (ret) - *ret = o; + if (ret_object) + *ret_object = o; if (ret_offset) *ret_offset = p; @@ -1252,7 +1264,7 @@ static int journal_file_link_data( return 0; } -static int next_hash_offset( +static int get_next_hash_offset( JournalFile *f, uint64_t *p, le64_t *next_hash_offset, @@ -1261,6 +1273,11 @@ static int next_hash_offset( uint64_t nextp; + assert(f); + assert(p); + assert(next_hash_offset); + assert(depth); + nextp = le64toh(READ_NOW(*next_hash_offset)); if (nextp > 0) { if (nextp <= *p) /* Refuse going in loops */ @@ -1280,15 +1297,19 @@ static int next_hash_offset( int journal_file_find_field_object_with_hash( JournalFile *f, - const void *field, uint64_t size, uint64_t hash, - Object **ret, uint64_t *ret_offset) { + const void *field, + uint64_t size, + uint64_t hash, + Object **ret_object, + uint64_t *ret_offset) { uint64_t p, osize, h, m, depth = 0; int r; assert(f); assert(f->header); - assert(field && size > 0); + assert(field); + assert(size > 0); /* If the field hash table is empty, we can't find anything */ if (le64toh(f->header->field_hash_table_size) <= 0) @@ -1318,15 +1339,15 @@ int journal_file_find_field_object_with_hash( le64toh(o->object.size) == osize && memcmp(o->field.payload, field, size) == 0) { - if (ret) - *ret = o; + if (ret_object) + *ret_object = o; if (ret_offset) *ret_offset = p; return 1; } - r = next_hash_offset( + r = get_next_hash_offset( f, &p, &o->field.next_hash_offset, @@ -1345,6 +1366,7 @@ uint64_t journal_file_hash_data( size_t sz) { assert(f); + assert(f->header); assert(data || sz == 0); /* We try to unify our codebase on siphash, hence new-styled journal files utilizing the keyed hash @@ -1358,23 +1380,29 @@ uint64_t journal_file_hash_data( int journal_file_find_field_object( JournalFile *f, - const void *field, uint64_t size, - Object **ret, uint64_t *ret_offset) { + const void *field, + uint64_t size, + Object **ret_object, + uint64_t *ret_offset) { assert(f); - assert(field && size > 0); + assert(field); + assert(size > 0); return journal_file_find_field_object_with_hash( f, field, size, journal_file_hash_data(f, field, size), - ret, ret_offset); + ret_object, ret_offset); } int journal_file_find_data_object_with_hash( JournalFile *f, - const void *data, uint64_t size, uint64_t hash, - Object **ret, uint64_t *ret_offset) { + const void *data, + uint64_t size, + uint64_t hash, + Object **ret_object, + uint64_t *ret_offset) { uint64_t p, h, m, depth = 0; int r; @@ -1417,8 +1445,8 @@ int journal_file_find_data_object_with_hash( assert(r > 0); /* journal_file_data_payload() always returns > 0 if no field is provided. */ if (memcmp_nn(data, size, d, rsize) == 0) { - if (ret) - *ret = o; + if (ret_object) + *ret_object = o; if (ret_offset) *ret_offset = p; @@ -1427,7 +1455,7 @@ int journal_file_find_data_object_with_hash( } next: - r = next_hash_offset( + r = get_next_hash_offset( f, &p, &o->data.next_hash_offset, @@ -1442,8 +1470,10 @@ int journal_file_find_data_object_with_hash( int journal_file_find_data_object( JournalFile *f, - const void *data, uint64_t size, - Object **ret, uint64_t *ret_offset) { + const void *data, + uint64_t size, + Object **ret_object, + uint64_t *ret_offset) { assert(f); assert(data || size == 0); @@ -1452,7 +1482,7 @@ int journal_file_find_data_object( f, data, size, journal_file_hash_data(f, data, size), - ret, ret_offset); + ret_object, ret_offset); } bool journal_field_valid(const char *p, size_t l, bool allow_protected) { @@ -1462,6 +1492,8 @@ bool journal_field_valid(const char *p, size_t l, bool allow_protected) { http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */ + assert(p); + if (l == SIZE_MAX) l = strlen(p); @@ -1493,8 +1525,10 @@ bool journal_field_valid(const char *p, size_t l, bool allow_protected) { static int journal_file_append_field( JournalFile *f, - const void *field, uint64_t size, - Object **ret, uint64_t *ret_offset) { + const void *field, + uint64_t size, + Object **ret_object, + uint64_t *ret_offset) { uint64_t hash, p; uint64_t osize; @@ -1502,14 +1536,15 @@ static int journal_file_append_field( int r; assert(f); - assert(field && size > 0); + assert(field); + assert(size > 0); if (!journal_field_valid(field, size, true)) return -EBADMSG; hash = journal_file_hash_data(f, field, size); - r = journal_file_find_field_object_with_hash(f, field, size, hash, ret, ret_offset); + r = journal_file_find_field_object_with_hash(f, field, size, hash, ret_object, ret_offset); if (r < 0) return r; if (r > 0) @@ -1536,8 +1571,8 @@ static int journal_file_append_field( return r; #endif - if (ret) { - r = journal_file_move_to_object(f, OBJECT_FIELD, p, ret); + if (ret_object) { + r = journal_file_move_to_object(f, OBJECT_FIELD, p, ret_object); if (r < 0) return r; } @@ -1551,13 +1586,16 @@ static int journal_file_append_field( static Compression maybe_compress_payload(JournalFile *f, uint8_t *dst, const uint8_t *src, uint64_t size, size_t *rsize) { Compression compression = COMPRESSION_NONE; + assert(f); + assert(f->header); + #if HAVE_COMPRESSION if (JOURNAL_FILE_COMPRESS(f) && size >= f->compress_threshold_bytes) { compression = compress_blob(src, size, dst, size - 1, rsize); - if (compression > 0) { + if (compression > 0) log_debug("Compressed data object %"PRIu64" -> %zu using %s", size, *rsize, compression_to_string(compression)); - } else + else /* Compression didn't work, we don't really care why, let's continue without compression */ compression = COMPRESSION_NONE; } @@ -1568,8 +1606,10 @@ static Compression maybe_compress_payload(JournalFile *f, uint8_t *dst, const ui static int journal_file_append_data( JournalFile *f, - const void *data, uint64_t size, - Object **ret, uint64_t *ret_offset) { + const void *data, + uint64_t size, + Object **ret_object, + uint64_t *ret_offset) { uint64_t hash, p, osize; Object *o, *fo; @@ -1585,7 +1625,7 @@ static int journal_file_append_data( hash = journal_file_hash_data(f, data, size); - r = journal_file_find_data_object_with_hash(f, data, size, hash, ret, ret_offset); + r = journal_file_find_data_object_with_hash(f, data, size, hash, ret_object, ret_offset); if (r < 0) return r; if (r > 0) @@ -1634,8 +1674,8 @@ static int journal_file_append_data( o->data.next_field_offset = fo->field.head_data_offset; fo->field.head_data_offset = le64toh(p); - if (ret) - *ret = o; + if (ret_object) + *ret_object = o; if (ret_offset) *ret_offset = p; @@ -1654,6 +1694,8 @@ static int maybe_decompress_payload( void **ret_data, size_t *ret_size) { + assert(f); + /* We can't read objects larger than 4G on a 32bit machine */ if ((uint64_t) (size_t) size != size) return -E2BIG; @@ -1672,8 +1714,10 @@ static int maybe_decompress_payload( compression_to_string(compression), size); if (r == 0) { - *ret_data = NULL; - *ret_size = 0; + if (ret_data) + *ret_data = NULL; + if (ret_size) + *ret_size = 0; return 0; } } @@ -1691,8 +1735,10 @@ static int maybe_decompress_payload( #endif } else { if (field && (size < field_length + 1 || memcmp(payload, field, field_length) != 0 || payload[field_length] != '=')) { - *ret_data = NULL; - *ret_size = 0; + if (ret_data) + *ret_data = NULL; + if (ret_size) + *ret_size = 0; return 0; } @@ -1719,9 +1765,8 @@ int journal_file_data_payload( Compression c; int r; + assert(f); assert(!field == (field_length == 0)); /* These must be specified together. */ - assert(ret_data); - assert(ret_size); if (!o) { r = journal_file_move_to_object(f, OBJECT_DATA, offset, &o); @@ -1762,6 +1807,7 @@ uint64_t journal_file_entry_n_items(JournalFile *f, Object *o) { uint64_t journal_file_entry_array_n_items(JournalFile *f, Object *o) { uint64_t sz; + assert(f); assert(o); if (o->object.type != OBJECT_ENTRY_ARRAY) @@ -1800,15 +1846,17 @@ static void write_entry_array_item(JournalFile *f, Object *o, uint64_t i, uint64 o->entry_array.items.regular[i] = htole64(p); } -static int link_entry_into_array(JournalFile *f, - le64_t *first, - le64_t *idx, - le32_t *tail, - le32_t *tidx, - uint64_t p) { - int r; +static int link_entry_into_array( + JournalFile *f, + le64_t *first, + le64_t *idx, + le32_t *tail, + le32_t *tidx, + uint64_t p) { + uint64_t n = 0, ap = 0, q, i, a, hidx; Object *o; + int r; assert(f); assert(f->header); @@ -1819,8 +1867,8 @@ static int link_entry_into_array(JournalFile *f, a = tail ? le32toh(*tail) : le64toh(*first); hidx = le64toh(READ_NOW(*idx)); i = tidx ? le32toh(READ_NOW(*tidx)) : hidx; - while (a > 0) { + while (a > 0) { r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); if (r < 0) return r; @@ -1884,13 +1932,14 @@ static int link_entry_into_array(JournalFile *f, return 0; } -static int link_entry_into_array_plus_one(JournalFile *f, - le64_t *extra, - le64_t *first, - le64_t *idx, - le32_t *tail, - le32_t *tidx, - uint64_t p) { +static int link_entry_into_array_plus_one( + JournalFile *f, + le64_t *extra, + le64_t *first, + le64_t *idx, + le32_t *tail, + le32_t *tidx, + uint64_t p) { uint64_t hidx; int r; @@ -1919,11 +1968,11 @@ static int link_entry_into_array_plus_one(JournalFile *f, return 0; } -static int journal_file_link_entry_item(JournalFile *f, Object *o, uint64_t offset, uint64_t p) { +static int journal_file_link_entry_item(JournalFile *f, uint64_t offset, uint64_t p) { + Object *o; int r; assert(f); - assert(o); assert(offset > 0); r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); @@ -1984,7 +2033,7 @@ static int journal_file_link_entry( * immediately but try to link the other entry items since it might still be possible to link * those if they don't require a new entry array to be allocated. */ - k = journal_file_link_entry_item(f, o, offset, items[i].object_offset); + k = journal_file_link_entry_item(f, offset, items[i].object_offset); if (k == -E2BIG) r = k; else if (k < 0) @@ -2013,9 +2062,12 @@ static int journal_file_append_entry_internal( const dual_timestamp *ts, const sd_id128_t *boot_id, uint64_t xor_hash, - const EntryItem items[], size_t n_items, + const EntryItem items[], + size_t n_items, uint64_t *seqnum, - Object **ret, uint64_t *ret_offset) { + Object **ret_object, + uint64_t *ret_offset) { + uint64_t np; uint64_t osize; Object *o; @@ -2023,8 +2075,8 @@ static int journal_file_append_entry_internal( assert(f); assert(f->header); - assert(items || n_items == 0); assert(ts); + assert(items || n_items == 0); osize = offsetof(Object, entry.items) + (n_items * journal_file_entry_item_size(f)); @@ -2053,8 +2105,8 @@ static int journal_file_append_entry_internal( if (r < 0) return r; - if (ret) - *ret = o; + if (ret_object) + *ret_object = o; if (ret_offset) *ret_offset = np; @@ -2152,12 +2204,14 @@ int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t) } static int entry_item_cmp(const EntryItem *a, const EntryItem *b) { - return CMP(a->object_offset, b->object_offset); + return CMP(ASSERT_PTR(a)->object_offset, ASSERT_PTR(b)->object_offset); } static size_t remove_duplicate_entry_items(EntryItem items[], size_t n) { size_t j = 1; + assert(items || n == 0); + if (n <= 1) return n; @@ -2172,9 +2226,11 @@ int journal_file_append_entry( JournalFile *f, const dual_timestamp *ts, const sd_id128_t *boot_id, - const struct iovec iovec[], unsigned n_iovec, + const struct iovec iovec[], + unsigned n_iovec, uint64_t *seqnum, - Object **ret, uint64_t *ret_offset) { + Object **ret_object, + uint64_t *ret_offset) { EntryItem *items; int r; @@ -2183,7 +2239,8 @@ int journal_file_append_entry( assert(f); assert(f->header); - assert(iovec && n_iovec > 0); + assert(iovec); + assert(n_iovec > 0); if (ts) { if (!VALID_REALTIME(ts->realtime)) @@ -2240,7 +2297,7 @@ int journal_file_append_entry( typesafe_qsort(items, n_iovec, entry_item_cmp); n_iovec = remove_duplicate_entry_items(items, n_iovec); - r = journal_file_append_entry_internal(f, ts, boot_id, xor_hash, items, n_iovec, seqnum, ret, ret_offset); + r = journal_file_append_entry_internal(f, ts, boot_id, xor_hash, items, n_iovec, seqnum, ret_object, ret_offset); /* If the memory mapping triggered a SIGBUS then we return an * IO error and ignore the error code passed down to us, since @@ -2275,6 +2332,8 @@ static void chain_cache_put( uint64_t total, uint64_t last_index) { + assert(h); + if (!ci) { /* If the chain item to cache for this chain is the * first one it's not worth caching anything */ @@ -2325,7 +2384,14 @@ static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) { return 1; } -static int bump_entry_array(JournalFile *f, Object *o, uint64_t offset, uint64_t first, direction_t direction, uint64_t *ret) { +static int bump_entry_array( + JournalFile *f, + Object *o, + uint64_t offset, + uint64_t first, + direction_t direction, + uint64_t *ret) { + uint64_t p, q = 0; int r; @@ -2333,8 +2399,10 @@ static int bump_entry_array(JournalFile *f, Object *o, uint64_t offset, uint64_t assert(offset); assert(ret); - if (direction == DIRECTION_DOWN) + if (direction == DIRECTION_DOWN) { + assert(o); return le64toh(o->entry_array.next_entry_array_offset); + } /* Entry array chains are a singly linked list, so to find the previous array in the chain, we have * to start iterating from the top. */ @@ -2365,15 +2433,18 @@ static int generic_array_get( uint64_t first, uint64_t i, direction_t direction, - Object **ret, uint64_t *ret_offset) { + Object **ret_object, + uint64_t *ret_offset) { - Object *o; uint64_t p = 0, a, t = 0, k; - int r; ChainCacheItem *ci; + Object *o; + int r; assert(f); + /* FIXME: fix return value assignment on success. */ + a = first; /* Try the chain cache first */ @@ -2437,7 +2508,7 @@ static int generic_array_get( do { p = journal_file_entry_array_item(f, o, i); - r = journal_file_move_to_object(f, OBJECT_ENTRY, p, ret); + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, ret_object); if (r >= 0) { /* Let's cache this item for the next invocation */ chain_cache_put(f->chain_cache, ci, first, a, journal_file_entry_array_item(f, o, 0), t, i); @@ -2472,16 +2543,19 @@ static int generic_array_get_plus_one( uint64_t first, uint64_t i, direction_t direction, - Object **ret, uint64_t *ret_offset) { + Object **ret_object, + uint64_t *ret_offset) { int r; assert(f); + /* FIXME: fix return value assignment on success. */ + if (i == 0) { - r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret); + r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret_object); if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) - return generic_array_get(f, first, 0, direction, ret, ret_offset); + return generic_array_get(f, first, 0, direction, ret_object, ret_offset); if (r < 0) return r; @@ -2491,7 +2565,7 @@ static int generic_array_get_plus_one( return 1; } - return generic_array_get(f, first, i - 1, direction, ret, ret_offset); + return generic_array_get(f, first, i - 1, direction, ret_object, ret_offset); } enum { @@ -2507,7 +2581,7 @@ static int generic_array_bisect( uint64_t needle, int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle), direction_t direction, - Object **ret, + Object **ret_object, uint64_t *ret_offset, uint64_t *ret_idx) { @@ -2527,8 +2601,8 @@ static int generic_array_bisect( uint64_t a, p, t = 0, i = 0, last_p = 0, last_index = UINT64_MAX; bool subtract_one = false; Object *array = NULL; - int r; ChainCacheItem *ci; + int r; assert(f); assert(test_object); @@ -2714,8 +2788,8 @@ found: else p = journal_file_entry_array_item(f, array, i); - if (ret) { - r = journal_file_move_to_object(f, OBJECT_ENTRY, p, ret); + if (ret_object) { + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, ret_object); if (r < 0) return r; } @@ -2737,7 +2811,7 @@ static int generic_array_bisect_plus_one( uint64_t needle, int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle), direction_t direction, - Object **ret, + Object **ret_object, uint64_t *ret_offset, uint64_t *ret_idx) { @@ -2774,7 +2848,7 @@ static int generic_array_bisect_plus_one( return 0; } - r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, ret_offset, ret_idx); + r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret_object, ret_offset, ret_idx); if (r == 0 && step_back) goto found; @@ -2785,8 +2859,8 @@ static int generic_array_bisect_plus_one( return r; found: - if (ret) { - r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret); + if (ret_object) { + r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret_object); if (r < 0) return r; } @@ -2816,7 +2890,7 @@ int journal_file_move_to_entry_by_offset( JournalFile *f, uint64_t p, direction_t direction, - Object **ret, + Object **ret_object, uint64_t *ret_offset) { assert(f); @@ -2829,7 +2903,7 @@ int journal_file_move_to_entry_by_offset( p, test_object_offset, direction, - ret, ret_offset, NULL); + ret_object, ret_offset, NULL); } static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) { @@ -2857,8 +2931,9 @@ int journal_file_move_to_entry_by_seqnum( JournalFile *f, uint64_t seqnum, direction_t direction, - Object **ret, + Object **ret_object, uint64_t *ret_offset) { + assert(f); assert(f->header); @@ -2869,7 +2944,7 @@ int journal_file_move_to_entry_by_seqnum( seqnum, test_object_seqnum, direction, - ret, ret_offset, NULL); + ret_object, ret_offset, NULL); } static int test_object_realtime(JournalFile *f, uint64_t p, uint64_t needle) { @@ -2897,8 +2972,9 @@ int journal_file_move_to_entry_by_realtime( JournalFile *f, uint64_t realtime, direction_t direction, - Object **ret, + Object **ret_object, uint64_t *ret_offset) { + assert(f); assert(f->header); @@ -2909,7 +2985,7 @@ int journal_file_move_to_entry_by_realtime( realtime, test_object_realtime, direction, - ret, ret_offset, NULL); + ret_object, ret_offset, NULL); } static int test_object_monotonic(JournalFile *f, uint64_t p, uint64_t needle) { @@ -2936,13 +3012,15 @@ static int test_object_monotonic(JournalFile *f, uint64_t p, uint64_t needle) { static int find_data_object_by_boot_id( JournalFile *f, sd_id128_t boot_id, - Object **o, - uint64_t *b) { + Object **ret_object, + uint64_t *ret_offset) { char t[STRLEN("_BOOT_ID=") + 32 + 1] = "_BOOT_ID="; + assert(f); + sd_id128_to_string(boot_id, t + 9); - return journal_file_find_data_object(f, t, sizeof(t) - 1, o, b); + return journal_file_find_data_object(f, t, sizeof(t) - 1, ret_object, ret_offset); } int journal_file_move_to_entry_by_monotonic( @@ -2950,7 +3028,7 @@ int journal_file_move_to_entry_by_monotonic( sd_id128_t boot_id, uint64_t monotonic, direction_t direction, - Object **ret, + Object **ret_object, uint64_t *ret_offset) { Object *o; @@ -2972,10 +3050,12 @@ int journal_file_move_to_entry_by_monotonic( monotonic, test_object_monotonic, direction, - ret, ret_offset, NULL); + ret_object, ret_offset, NULL); } void journal_file_reset_location(JournalFile *f) { + assert(f); + f->location_type = LOCATION_HEAD; f->current_offset = 0; f->current_seqnum = 0; @@ -2986,6 +3066,9 @@ void journal_file_reset_location(JournalFile *f) { } void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) { + assert(f); + assert(o); + f->location_type = LOCATION_SEEK; f->current_offset = offset; f->current_seqnum = le64toh(o->entry.seqnum); @@ -3061,7 +3144,8 @@ int journal_file_next_entry( JournalFile *f, uint64_t p, direction_t direction, - Object **ret, uint64_t *ret_offset) { + Object **ret_object, + uint64_t *ret_offset) { uint64_t i, n, ofs; int r; @@ -3069,6 +3153,8 @@ int journal_file_next_entry( assert(f); assert(f->header); + /* FIXME: fix return value assignment. */ + n = le64toh(READ_NOW(f->header->n_entries)); if (n <= 0) return 0; @@ -3093,7 +3179,7 @@ int journal_file_next_entry( } /* And jump to it */ - r = generic_array_get(f, le64toh(f->header->entry_array_offset), i, direction, ret, &ofs); + r = generic_array_get(f, le64toh(f->header->entry_array_offset), i, direction, ret_object, &ofs); if (r <= 0) return r; @@ -3113,7 +3199,8 @@ int journal_file_next_entry_for_data( JournalFile *f, Object *d, direction_t direction, - Object **ret, uint64_t *ret_offset) { + Object **ret_object, + uint64_t *ret_offset) { uint64_t i, n, ofs; int r; @@ -3122,6 +3209,8 @@ int journal_file_next_entry_for_data( assert(d); assert(d->object.type == OBJECT_DATA); + /* FIXME: fix return value assignment. */ + n = le64toh(READ_NOW(d->data.n_entries)); if (n <= 0) return n; @@ -3133,7 +3222,7 @@ int journal_file_next_entry_for_data( le64toh(d->data.entry_array_offset), i, direction, - ret, &ofs); + ret_object, &ofs); if (r <= 0) return r; @@ -3171,11 +3260,12 @@ int journal_file_move_to_entry_by_monotonic_for_data( sd_id128_t boot_id, uint64_t monotonic, direction_t direction, - Object **ret, uint64_t *ret_offset) { + Object **ret_object, + uint64_t *ret_offset) { + uint64_t b, z, entry_offset, entry_array_offset, n_entries; Object *o; int r; - uint64_t b, z, entry_offset, entry_array_offset, n_entries; assert(f); assert(d); @@ -3238,8 +3328,8 @@ int journal_file_move_to_entry_by_monotonic_for_data( return r; if (p == q) { - if (ret) { - r = journal_file_move_to_object(f, OBJECT_ENTRY, q, ret); + if (ret_object) { + r = journal_file_move_to_object(f, OBJECT_ENTRY, q, ret_object); if (r < 0) return r; } @@ -3259,7 +3349,8 @@ int journal_file_move_to_entry_by_seqnum_for_data( Object *d, uint64_t seqnum, direction_t direction, - Object **ret, uint64_t *ret_offset) { + Object **ret_object, + uint64_t *ret_offset) { assert(f); assert(d); @@ -3273,7 +3364,7 @@ int journal_file_move_to_entry_by_seqnum_for_data( seqnum, test_object_seqnum, direction, - ret, ret_offset, NULL); + ret_object, ret_offset, NULL); } int journal_file_move_to_entry_by_realtime_for_data( @@ -3300,8 +3391,8 @@ int journal_file_move_to_entry_by_realtime_for_data( void journal_file_dump(JournalFile *f) { Object *o; - int r; uint64_t p; + int r; assert(f); assert(f->header); @@ -3587,9 +3678,9 @@ int journal_file_open( void *h; int r; - assert(ret); assert(fd >= 0 || fname); assert(mmap_cache); + assert(ret); if (!IN_SET((open_flags & O_ACCMODE), O_RDONLY, O_RDWR)) return -EINVAL; @@ -3893,7 +3984,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 assert(from); assert(to); assert(o); - assert(p); + assert(p > 0); if (!journal_file_writable(to)) return -EPERM; @@ -3917,7 +4008,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 r = journal_file_data_payload(from, NULL, q, NULL, 0, 0, &data, &l); if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) { log_debug_errno(r, "Entry item %"PRIu64" data object is bad, skipping over it: %m", i); - continue; + goto next; } if (r < 0) return r; @@ -3939,6 +4030,13 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 .object_offset = h, .hash = le64toh(u->data.hash), }; + + next: + /* The above journal_file_data_payload() may clear or overwrite cached object. Hence, we need + * to re-read the object from the cache. */ + r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; } r = journal_file_append_entry_internal(to, &ts, boot_id, xor_hash, items, n, NULL, NULL, NULL); @@ -3964,35 +4062,37 @@ void journal_reset_metrics(JournalMetrics *m) { }; } -int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) { +int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *ret_from, usec_t *ret_to) { assert(f); assert(f->header); - assert(from || to); + assert(ret_from || ret_to); - if (from) { + if (ret_from) { if (f->header->head_entry_realtime == 0) return -ENOENT; - *from = le64toh(f->header->head_entry_realtime); + *ret_from = le64toh(f->header->head_entry_realtime); } - if (to) { + if (ret_to) { if (f->header->tail_entry_realtime == 0) return -ENOENT; - *to = le64toh(f->header->tail_entry_realtime); + *ret_to = le64toh(f->header->tail_entry_realtime); } return 1; } -int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *from, usec_t *to) { +int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *ret_from, usec_t *ret_to) { Object *o; uint64_t p; int r; assert(f); - assert(from || to); + assert(ret_from || ret_to); + + /* FIXME: fix return value assignment on success with 0. */ r = find_data_object_by_boot_id(f, boot_id, &o, &p); if (r <= 0) @@ -4001,15 +4101,15 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, u if (le64toh(o->data.n_entries) <= 0) return 0; - if (from) { + if (ret_from) { r = journal_file_move_to_object(f, OBJECT_ENTRY, le64toh(o->data.entry_offset), &o); if (r < 0) return r; - *from = le64toh(o->entry.monotonic); + *ret_from = le64toh(o->entry.monotonic); } - if (to) { + if (ret_to) { r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; @@ -4023,7 +4123,7 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, u if (r <= 0) return r; - *to = le64toh(o->entry.monotonic); + *ret_to = le64toh(o->entry.monotonic); } return 1; diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h index e5b9765471e..1f3c80c9125 100644 --- a/src/libsystemd/sd-journal/journal-file.h +++ b/src/libsystemd/sd-journal/journal-file.h @@ -249,38 +249,38 @@ static inline size_t journal_file_entry_array_item_size(JournalFile *f) { uint64_t journal_file_hash_table_n_items(Object *o) _pure_; -int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *ret_offset); +int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret_object, uint64_t *ret_offset); int journal_file_append_entry( JournalFile *f, const dual_timestamp *ts, const sd_id128_t *boot_id, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, - Object **ret, + Object **ret_object, uint64_t *ret_offset); -int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *ret_offset); -int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *ret_offset); +int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret_object, uint64_t *ret_offset); +int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret_object, uint64_t *ret_offset); -int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *ret_offset); -int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret, uint64_t *ret_offset); +int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret_object, uint64_t *ret_offset); +int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret_object, uint64_t *ret_offset); void journal_file_reset_location(JournalFile *f); void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset); int journal_file_compare_locations(JournalFile *af, JournalFile *bf); -int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *ret_offset); +int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret_object, uint64_t *ret_offset); -int journal_file_next_entry_for_data(JournalFile *f, Object *d, direction_t direction, Object **ret, uint64_t *ret_offset); +int journal_file_next_entry_for_data(JournalFile *f, Object *d, direction_t direction, Object **ret_object, uint64_t *ret_offset); -int journal_file_move_to_entry_by_offset(JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *ret_offset); -int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *ret_offset); -int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *ret_offset); -int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *ret_offset); +int journal_file_move_to_entry_by_offset(JournalFile *f, uint64_t p, direction_t direction, Object **ret_object, uint64_t *ret_offset); +int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret_object, uint64_t *ret_offset); +int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret_object, uint64_t *ret_offset); +int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret_object, uint64_t *ret_offset); -int journal_file_move_to_entry_by_offset_for_data(JournalFile *f, Object *d, uint64_t p, direction_t direction, Object **ret, uint64_t *ret_offset); -int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, Object *d, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *ret_offset); -int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, Object *d, uint64_t realtime, direction_t direction, Object **ret, uint64_t *ret_offset); -int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, Object *d, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *ret_offset); +int journal_file_move_to_entry_by_offset_for_data(JournalFile *f, Object *d, uint64_t p, direction_t direction, Object **ret_object, uint64_t *ret_offset); +int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, Object *d, uint64_t seqnum, direction_t direction, Object **ret_object, uint64_t *ret_offset); +int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, Object *d, uint64_t realtime, direction_t direction, Object **ret_object, uint64_t *ret_offset); +int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, Object *d, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret_object, uint64_t *ret_offset); int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p); @@ -297,8 +297,8 @@ int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t) void journal_reset_metrics(JournalMetrics *m); -int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to); -int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to); +int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *ret_from, usec_t *ret_to); +int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *ret_from, usec_t *ret_to); bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec, int log_level); diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c index 5a75994d159..53c0b2a01e9 100644 --- a/src/libsystemd/sd-journal/sd-journal.c +++ b/src/libsystemd/sd-journal/sd-journal.c @@ -2264,8 +2264,8 @@ static bool field_is_valid(const char *field) { _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) { JournalFile *f; size_t field_length; - int r; Object *o; + int r; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); @@ -2296,10 +2296,10 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** p = journal_file_entry_item_object_offset(f, o, i); r = journal_file_data_payload(f, NULL, p, field, field_length, j->data_threshold, &d, &l); if (r == 0) - continue; + goto next; if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) { log_debug_errno(r, "Entry item %"PRIu64" data object is bad, skipping over it: %m", i); - continue; + goto next; } if (r < 0) return r; @@ -2308,6 +2308,12 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** *size = l; return 0; + + next: + /* journal_file_data_payload() may clear or overwrite cached object. */ + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); + if (r < 0) + return r; } return -ENOENT; @@ -2343,7 +2349,7 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t r = journal_file_data_payload(f, NULL, p, NULL, 0, j->data_threshold, &d, &l); if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) { log_debug_errno(r, "Entry item %"PRIu64" data object is bad, skipping over it: %m", j->current_field); - continue; + goto next; } if (r < 0) return r; @@ -2355,6 +2361,12 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t j->current_field++; return 1; + + next: + /* journal_file_data_payload() may clear or overwrite cached object. */ + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); + if (r < 0) + return r; } return 0;