const void *data, uint64_t size, uint64_t hash,
Object **ret, uint64_t *ret_offset) {
- uint64_t p, osize, h, m, depth = 0;
+ uint64_t p, h, m, depth = 0;
int r;
assert(f);
if (r < 0)
return r;
- osize = offsetof(Object, data.payload) + size;
-
m = le64toh(READ_NOW(f->header->data_hash_table_size)) / sizeof(HashItem);
if (m <= 0)
return -EBADMSG;
p = le64toh(f->data_hash_table[h].head_hash_offset);
while (p > 0) {
- Compression c;
Object *o;
+ void *d;
+ size_t rsize;
r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
if (r < 0)
if (le64toh(o->data.hash) != hash)
goto next;
- c = COMPRESSION_FROM_OBJECT(o);
- if (c < 0)
- return -EPROTONOSUPPORT;
- if (c != COMPRESSION_NONE) {
-#if HAVE_COMPRESSION
- uint64_t l;
- size_t rsize = 0;
-
- l = le64toh(READ_NOW(o->object.size));
- if (l <= offsetof(Object, data.payload))
- return -EBADMSG;
-
- l -= offsetof(Object, data.payload);
-
- r = decompress_blob(c, o->data.payload, l, &f->compress_buffer, &rsize, 0);
- if (r < 0)
- return r;
-
- if (rsize == size &&
- memcmp(f->compress_buffer, data, size) == 0) {
-
- if (ret)
- *ret = o;
-
- if (ret_offset)
- *ret_offset = p;
-
- return 1;
- }
-#else
- return -EPROTONOSUPPORT;
-#endif
- } else if (le64toh(o->object.size) == osize &&
- memcmp(o->data.payload, data, size) == 0) {
+ r = journal_file_data_payload(f, o, p, NULL, 0, 0, &d, &rsize);
+ if (r < 0)
+ return r;
+ assert(r > 0); /* journal_file_data_payload() always returns > 0 if no field is provided. */
- if (ret)
+ if (memcmp_nn(data, size, d, rsize) == 0) {
+ if (ret)
*ret = o;
if (ret_offset)
return 0;
}
+static int maybe_decompress_payload(
+ JournalFile *f,
+ uint8_t *payload,
+ uint64_t size,
+ Compression compression,
+ const char *field,
+ size_t field_length,
+ size_t data_threshold,
+ void **ret_data,
+ size_t *ret_size) {
+
+ /* We can't read objects larger than 4G on a 32bit machine */
+ if ((uint64_t) (size_t) size != size)
+ return -E2BIG;
+
+ if (compression != COMPRESSION_NONE) {
+#if HAVE_COMPRESSION
+ size_t rsize;
+ int r;
+
+ if (field) {
+ r = decompress_startswith(compression, payload, size, &f->compress_buffer, field,
+ field_length, '=');
+ if (r < 0)
+ return log_debug_errno(r,
+ "Cannot decompress %s object of length %" PRIu64 ": %m",
+ compression_to_string(compression),
+ size);
+ if (r == 0) {
+ *ret_data = NULL;
+ *ret_size = 0;
+ return 0;
+ }
+ }
+
+ r = decompress_blob(compression, payload, size, &f->compress_buffer, &rsize, 0);
+ if (r < 0)
+ return r;
+
+ if (ret_data)
+ *ret_data = f->compress_buffer;
+ if (ret_size)
+ *ret_size = rsize;
+#else
+ return -EPROTONOSUPPORT;
+#endif
+ } else {
+ if (field && (size < field_length + 1 || memcmp(payload, field, field_length) != 0 || payload[field_length] != '=')) {
+ *ret_data = NULL;
+ *ret_size = 0;
+ return 0;
+ }
+
+ if (ret_data)
+ *ret_data = payload;
+ if (ret_size)
+ *ret_size = (size_t) size;
+ }
+
+ return 1;
+}
+
+int journal_file_data_payload(
+ JournalFile *f,
+ Object *o,
+ uint64_t offset,
+ const char *field,
+ size_t field_length,
+ size_t data_threshold,
+ void **ret_data,
+ size_t *ret_size) {
+
+ uint64_t size;
+ Compression c;
+ int r;
+
+ 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);
+ if (r < 0)
+ return r;
+ }
+
+ size = le64toh(READ_NOW(o->object.size));
+ if (size < offsetof(Object, data.payload))
+ return -EBADMSG;
+
+ size -= offsetof(Object, data.payload);
+
+ c = COMPRESSION_FROM_OBJECT(o);
+ if (c < 0)
+ return -EPROTONOSUPPORT;
+
+ return maybe_decompress_payload(f, o->data.payload, size, c, field, field_length, data_threshold,
+ ret_data, ret_size);
+}
+
uint64_t journal_file_entry_n_items(JournalFile *f, Object *o) {
uint64_t sz;
items = newa(EntryItem, n);
for (uint64_t i = 0; i < n; i++) {
- Compression c;
- uint64_t l, h;
- size_t t;
+ uint64_t h;
void *data;
+ size_t l;
Object *u;
q = journal_file_entry_item_object_offset(from, o, i);
-
- r = journal_file_move_to_object(from, OBJECT_DATA, q, &o);
+ 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;
+ }
if (r < 0)
return r;
-
- l = le64toh(READ_NOW(o->object.size));
- if (l < offsetof(Object, data.payload))
- return -EBADMSG;
-
- l -= offsetof(Object, data.payload);
- t = (size_t) l;
-
- /* We hit the limit on 32bit machines */
- if ((uint64_t) t != l)
- return -E2BIG;
-
- c = COMPRESSION_FROM_OBJECT(o);
- if (c < 0)
- return -EPROTONOSUPPORT;
- if (c != COMPRESSION_NONE) {
-#if HAVE_COMPRESSION
- size_t rsize = 0;
-
- r = decompress_blob(
- c,
- o->data.payload, l,
- &from->compress_buffer, &rsize,
- 0);
- if (r < 0)
- return r;
-
- data = from->compress_buffer;
- l = rsize;
-#else
- return -EPROTONOSUPPORT;
-#endif
- } else
- data = o->data.payload;
+ assert(r > 0);
if (l == 0)
return -EBADMSG;
.object_offset = h,
.hash = le64toh(u->data.hash),
};
-
- 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);
uint64_t n = journal_file_entry_n_items(f, o);
for (uint64_t i = 0; i < n; i++) {
- Object *d;
- uint64_t p, l;
- size_t t;
- Compression c;
+ uint64_t p;
+ void *d;
+ size_t l;
p = journal_file_entry_item_object_offset(f, o, i);
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &d);
+ r = journal_file_data_payload(f, NULL, p, field, field_length, j->data_threshold, &d, &l);
+ if (r == 0)
+ continue;
if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) {
log_debug_errno(r, "Entry item %"PRIu64" data object is bad, skipping over it: %m", i);
continue;
if (r < 0)
return r;
- l = le64toh(d->object.size) - offsetof(Object, data.payload);
-
- c = COMPRESSION_FROM_OBJECT(d);
- if (c < 0)
- return -EPROTONOSUPPORT;
- if (c != COMPRESSION_NONE) {
-#if HAVE_COMPRESSION
- r = decompress_startswith(
- c,
- d->data.payload, l,
- &f->compress_buffer,
- field, field_length, '=');
- if (r < 0)
- log_debug_errno(r, "Cannot decompress %s object of length %"PRIu64" at offset "OFSfmt": %m",
- compression_to_string(c), l, p);
- else if (r > 0) {
-
- size_t rsize;
-
- r = decompress_blob(
- c,
- d->data.payload, l,
- &f->compress_buffer, &rsize,
- j->data_threshold);
- if (r < 0)
- return r;
-
- *data = f->compress_buffer;
- *size = (size_t) rsize;
-
- return 0;
- }
-#else
- return -EPROTONOSUPPORT;
-#endif
- } else if (l >= field_length+1 &&
- memcmp(d->data.payload, field, field_length) == 0 &&
- d->data.payload[field_length] == '=') {
-
- t = (size_t) l;
-
- if ((uint64_t) t != l)
- return -E2BIG;
+ *data = d;
+ *size = l;
- *data = d->data.payload;
- *size = t;
-
- return 0;
- }
+ return 0;
}
return -ENOENT;
}
-static int return_data(
- sd_journal *j,
- JournalFile *f,
- Object *o,
- const void **ret_data,
- size_t *ret_size) {
-
- Compression c;
- uint64_t l;
- size_t t;
-
- assert(j);
- assert(f);
-
- l = le64toh(READ_NOW(o->object.size));
- if (l < offsetof(Object, data.payload))
- return -EBADMSG;
- l -= offsetof(Object, data.payload);
-
- /* We can't read objects larger than 4G on a 32bit machine */
- t = (size_t) l;
- if ((uint64_t) t != l)
- return -E2BIG;
-
- c = COMPRESSION_FROM_OBJECT(o);
- if (c < 0)
- return -EPROTONOSUPPORT;
- if (c != COMPRESSION_NONE) {
-#if HAVE_COMPRESSION
- size_t rsize;
- int r;
-
- r = decompress_blob(
- c,
- o->data.payload, l,
- &f->compress_buffer, &rsize,
- j->data_threshold);
- if (r < 0)
- return r;
-
- if (ret_data)
- *ret_data = f->compress_buffer;
- if (ret_size)
- *ret_size = (size_t) rsize;
-#else
- return -EPROTONOSUPPORT;
-#endif
- } else {
- if (ret_data)
- *ret_data = o->data.payload;
- if (ret_size)
- *ret_size = t;
- }
-
- return 0;
-}
-
_public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) {
JournalFile *f;
Object *o;
for (uint64_t n = journal_file_entry_n_items(f, o); j->current_field < n; j->current_field++) {
uint64_t p;
+ void *d;
+ size_t l;
p = journal_file_entry_item_object_offset(f, o, j->current_field);
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
+ 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;
}
if (r < 0)
return r;
+ assert(r > 0);
- r = return_data(j, f, o, data, size);
- if (r == -EBADMSG) {
- log_debug("Entry item %"PRIu64" data payload is bad, skipping over it.", j->current_field);
- continue;
- }
- if (r < 0)
- return r;
+ *data = d;
+ *size = l;
j->current_field++;
for (;;) {
JournalFile *of;
Object *o;
- const void *odata;
+ void *odata;
size_t ol;
bool found;
int r;
j->unique_offset,
o->object.type, OBJECT_DATA);
- r = return_data(j, j->unique_file, o, &odata, &ol);
+ r = journal_file_data_payload(j->unique_file, o, j->unique_offset, NULL, 0,
+ j->data_threshold, &odata, &ol);
if (r < 0)
return r;
if (found)
continue;
- r = return_data(j, j->unique_file, o, ret_data, ret_size);
- if (r < 0)
- return r;
+ *ret_data = odata;
+ *ret_size = ol;
return 1;
}