journal: Make the output of --update-catalog deterministic
The use of an unordered hashmap means that the output of 'journalctl --update-catalog' differs between runs despite there being no changes in the input files. By changing all instances of Hashmap to OrderedHashmap we fix this, and now the catalog is reproducible. Motivation: https://reproducible-builds.org Signed-off-by: Daniel Edgecumbe <git@esotericnonsense.com>
This commit is contained in:
committed by
Zbigniew Jędrzejewski-Szmek
parent
d5698dc1d9
commit
a95686bb5d
@@ -9,12 +9,12 @@
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
_cleanup_(unlink_tempfilep) char name[] = "/tmp/fuzz-catalog.XXXXXX";
|
||||
_cleanup_close_ int fd = -1;
|
||||
_cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
|
||||
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
|
||||
|
||||
if (!getenv("SYSTEMD_LOG_LEVEL"))
|
||||
log_set_max_level(LOG_CRIT);
|
||||
|
||||
assert_se(h = hashmap_new(&catalog_hash_ops));
|
||||
assert_se(h = ordered_hashmap_new(&catalog_hash_ops));
|
||||
|
||||
fd = mkostemp_safe(name);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
+12
-12
@@ -143,7 +143,7 @@ static char *combine_entries(const char *one, const char *two) {
|
||||
}
|
||||
|
||||
static int finish_item(
|
||||
Hashmap *h,
|
||||
OrderedHashmap *h,
|
||||
sd_id128_t id,
|
||||
const char *language,
|
||||
char *payload, size_t payload_size) {
|
||||
@@ -165,14 +165,14 @@ static int finish_item(
|
||||
strcpy(i->language, language);
|
||||
}
|
||||
|
||||
prev = hashmap_get(h, i);
|
||||
prev = ordered_hashmap_get(h, i);
|
||||
if (prev) {
|
||||
/* Already have such an item, combine them */
|
||||
combined = combine_entries(payload, prev);
|
||||
if (!combined)
|
||||
return log_oom();
|
||||
|
||||
if (hashmap_update(h, i, combined) < 0)
|
||||
if (ordered_hashmap_update(h, i, combined) < 0)
|
||||
return log_oom();
|
||||
combined = NULL;
|
||||
} else {
|
||||
@@ -181,7 +181,7 @@ static int finish_item(
|
||||
if (!combined)
|
||||
return log_oom();
|
||||
|
||||
if (hashmap_put(h, i, combined) < 0)
|
||||
if (ordered_hashmap_put(h, i, combined) < 0)
|
||||
return log_oom();
|
||||
i = NULL;
|
||||
combined = NULL;
|
||||
@@ -247,7 +247,7 @@ static int catalog_entry_lang(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int catalog_import_file(Hashmap *h, const char *path) {
|
||||
int catalog_import_file(OrderedHashmap *h, const char *path) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *payload = NULL;
|
||||
size_t payload_size = 0, payload_allocated = 0;
|
||||
@@ -446,7 +446,7 @@ int catalog_update(const char* database, const char* root, const char* const* di
|
||||
_cleanup_strv_free_ char **files = NULL;
|
||||
char **f;
|
||||
_cleanup_(strbuf_cleanupp) struct strbuf *sb = NULL;
|
||||
_cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
|
||||
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
|
||||
_cleanup_free_ CatalogItem *items = NULL;
|
||||
ssize_t offset;
|
||||
char *payload;
|
||||
@@ -456,7 +456,7 @@ int catalog_update(const char* database, const char* root, const char* const* di
|
||||
int r;
|
||||
int64_t sz;
|
||||
|
||||
h = hashmap_new(&catalog_hash_ops);
|
||||
h = ordered_hashmap_new(&catalog_hash_ops);
|
||||
sb = strbuf_new();
|
||||
if (!h || !sb)
|
||||
return log_oom();
|
||||
@@ -472,18 +472,18 @@ int catalog_update(const char* database, const char* root, const char* const* di
|
||||
return log_error_errno(r, "Failed to import file '%s': %m", *f);
|
||||
}
|
||||
|
||||
if (hashmap_size(h) <= 0) {
|
||||
if (ordered_hashmap_size(h) <= 0) {
|
||||
log_info("No items in catalog.");
|
||||
return 0;
|
||||
} else
|
||||
log_debug("Found %u items in catalog.", hashmap_size(h));
|
||||
log_debug("Found %u items in catalog.", ordered_hashmap_size(h));
|
||||
|
||||
items = new(CatalogItem, hashmap_size(h));
|
||||
items = new(CatalogItem, ordered_hashmap_size(h));
|
||||
if (!items)
|
||||
return log_oom();
|
||||
|
||||
n = 0;
|
||||
HASHMAP_FOREACH_KEY(payload, i, h, j) {
|
||||
ORDERED_HASHMAP_FOREACH_KEY(payload, i, h, j) {
|
||||
log_debug("Found " SD_ID128_FORMAT_STR ", language %s",
|
||||
SD_ID128_FORMAT_VAL(i->id),
|
||||
isempty(i->language) ? "C" : i->language);
|
||||
@@ -496,7 +496,7 @@ int catalog_update(const char* database, const char* root, const char* const* di
|
||||
items[n++] = *i;
|
||||
}
|
||||
|
||||
assert(n == hashmap_size(h));
|
||||
assert(n == ordered_hashmap_size(h));
|
||||
typesafe_qsort(items, n, catalog_compare_func);
|
||||
|
||||
strbuf_complete(sb);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "hashmap.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
int catalog_import_file(Hashmap *h, const char *path);
|
||||
int catalog_import_file(OrderedHashmap *h, const char *path);
|
||||
int catalog_update(const char* database, const char* root, const char* const* dirs);
|
||||
int catalog_get(const char* database, sd_id128_t id, char **data);
|
||||
int catalog_list(FILE *f, const char* database, bool oneline);
|
||||
|
||||
+15
-15
@@ -26,15 +26,15 @@ static const char *no_catalog_dirs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static Hashmap* test_import(const char* contents, ssize_t size, int code) {
|
||||
static OrderedHashmap* test_import(const char* contents, ssize_t size, int code) {
|
||||
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-catalog.XXXXXX";
|
||||
_cleanup_close_ int fd;
|
||||
Hashmap *h;
|
||||
OrderedHashmap *h;
|
||||
|
||||
if (size < 0)
|
||||
size = strlen(contents);
|
||||
|
||||
assert_se(h = hashmap_new(&catalog_hash_ops));
|
||||
assert_se(h = ordered_hashmap_new(&catalog_hash_ops));
|
||||
|
||||
fd = mkostemp_safe(name);
|
||||
assert_se(fd >= 0);
|
||||
@@ -46,14 +46,14 @@ static Hashmap* test_import(const char* contents, ssize_t size, int code) {
|
||||
}
|
||||
|
||||
static void test_catalog_import_invalid(void) {
|
||||
_cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
|
||||
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
|
||||
|
||||
h = test_import("xxx", -1, -EINVAL);
|
||||
assert_se(hashmap_isempty(h));
|
||||
assert_se(ordered_hashmap_isempty(h));
|
||||
}
|
||||
|
||||
static void test_catalog_import_badid(void) {
|
||||
_cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
|
||||
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
|
||||
const char *input =
|
||||
"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededede\n" \
|
||||
"Subject: message\n" \
|
||||
@@ -63,7 +63,7 @@ static void test_catalog_import_badid(void) {
|
||||
}
|
||||
|
||||
static void test_catalog_import_one(void) {
|
||||
_cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
|
||||
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
|
||||
char *payload;
|
||||
Iterator j;
|
||||
|
||||
@@ -78,9 +78,9 @@ static void test_catalog_import_one(void) {
|
||||
"payload\n";
|
||||
|
||||
h = test_import(input, -1, 0);
|
||||
assert_se(hashmap_size(h) == 1);
|
||||
assert_se(ordered_hashmap_size(h) == 1);
|
||||
|
||||
HASHMAP_FOREACH(payload, h, j) {
|
||||
ORDERED_HASHMAP_FOREACH(payload, h, j) {
|
||||
printf("expect: %s\n", expect);
|
||||
printf("actual: %s\n", payload);
|
||||
assert_se(streq(expect, payload));
|
||||
@@ -88,7 +88,7 @@ static void test_catalog_import_one(void) {
|
||||
}
|
||||
|
||||
static void test_catalog_import_merge(void) {
|
||||
_cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
|
||||
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
|
||||
char *payload;
|
||||
Iterator j;
|
||||
|
||||
@@ -114,15 +114,15 @@ static void test_catalog_import_merge(void) {
|
||||
"override payload\n";
|
||||
|
||||
h = test_import(input, -1, 0);
|
||||
assert_se(hashmap_size(h) == 1);
|
||||
assert_se(ordered_hashmap_size(h) == 1);
|
||||
|
||||
HASHMAP_FOREACH(payload, h, j) {
|
||||
ORDERED_HASHMAP_FOREACH(payload, h, j) {
|
||||
assert_se(streq(combined, payload));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_catalog_import_merge_no_body(void) {
|
||||
_cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
|
||||
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
|
||||
char *payload;
|
||||
Iterator j;
|
||||
|
||||
@@ -147,9 +147,9 @@ static void test_catalog_import_merge_no_body(void) {
|
||||
"payload\n";
|
||||
|
||||
h = test_import(input, -1, 0);
|
||||
assert_se(hashmap_size(h) == 1);
|
||||
assert_se(ordered_hashmap_size(h) == 1);
|
||||
|
||||
HASHMAP_FOREACH(payload, h, j) {
|
||||
ORDERED_HASHMAP_FOREACH(payload, h, j) {
|
||||
assert_se(streq(combined, payload));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user