mirror of
https://github.com/systemd/systemd.git
synced 2025-01-10 05:18:17 +03:00
journal: Introduce journal_file_data_payload()
journal_file_data_payload() retrieves the payload of a Data object, optionally decompressing it and checking to see if matches a given field. This function replaces all the decompression code in the sd-journal codebase with a single function. This commit should not introduce any changes in sd-journal behavior.
This commit is contained in:
parent
a9089a6604
commit
0e35afff1d
@ -1369,7 +1369,7 @@ int journal_file_find_data_object_with_hash(
|
||||
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);
|
||||
@ -1385,8 +1385,6 @@ int journal_file_find_data_object_with_hash(
|
||||
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;
|
||||
@ -1395,8 +1393,9 @@ int journal_file_find_data_object_with_hash(
|
||||
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)
|
||||
@ -1405,42 +1404,13 @@ int journal_file_find_data_object_with_hash(
|
||||
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;
|
||||
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. */
|
||||
|
||||
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) {
|
||||
|
||||
if (ret)
|
||||
if (memcmp_nn(data, size, d, rsize) == 0) {
|
||||
if (ret)
|
||||
*ret = o;
|
||||
|
||||
if (ret_offset)
|
||||
@ -1658,6 +1628,106 @@ static int journal_file_append_data(
|
||||
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;
|
||||
|
||||
@ -3807,51 +3877,20 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
|
||||
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;
|
||||
@ -3869,10 +3908,6 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
|
||||
.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);
|
||||
|
@ -212,6 +212,17 @@ static inline size_t journal_file_entry_item_size(JournalFile *f) {
|
||||
}
|
||||
|
||||
uint64_t journal_file_entry_n_items(JournalFile *f, Object *o) _pure_;
|
||||
|
||||
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 journal_file_entry_array_n_items(JournalFile *f, Object *o) _pure_;
|
||||
|
||||
static inline uint64_t journal_file_entry_array_item(JournalFile *f, Object *o, size_t i) {
|
||||
|
@ -2289,13 +2289,14 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **
|
||||
|
||||
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;
|
||||
@ -2303,117 +2304,15 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
l = le64toh(d->object.size) - offsetof(Object, data.payload);
|
||||
*data = d;
|
||||
*size = l;
|
||||
|
||||
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->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;
|
||||
@ -2437,23 +2336,21 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t
|
||||
|
||||
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++;
|
||||
|
||||
@ -2925,7 +2822,7 @@ _public_ int sd_journal_enumerate_unique(
|
||||
for (;;) {
|
||||
JournalFile *of;
|
||||
Object *o;
|
||||
const void *odata;
|
||||
void *odata;
|
||||
size_t ol;
|
||||
bool found;
|
||||
int r;
|
||||
@ -2969,7 +2866,8 @@ _public_ int sd_journal_enumerate_unique(
|
||||
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;
|
||||
|
||||
@ -3016,9 +2914,8 @@ _public_ int sd_journal_enumerate_unique(
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user