+static int boot_id_cmp(const void *a, const void *b) {
+ uint64_t _a, _b;
+
+ _a = ((const boot_id_t *)a)->timestamp;
+ _b = ((const boot_id_t *)b)->timestamp;
+
+ return _a < _b ? -1 : (_a > _b ? 1 : 0);
+}
+
+static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) {
+ int r;
+ const void *data;
+ unsigned int id_count = 0;
+ size_t length, allocated = 0;
+ boot_id_t ref_boot_id, *id;
+ _cleanup_free_ boot_id_t *all_ids = NULL;
+ bool find_first_boot = false, ref_boot_found = false;
+
+ assert(j);
+ assert(boot_id);
+
+ if (relative == 0)
+ return 0;
+
+ if (sd_id128_equal(*boot_id, SD_ID128_NULL) && relative > 0) {
+ find_first_boot = true;
+ relative--;
+ }
+
+ r = sd_journal_query_unique(j, "_BOOT_ID");
+ if (r < 0)
+ return r;
+
+ SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
+ if (length < strlen("_BOOT_ID="))
+ continue;
+
+ if (!GREEDY_REALLOC(all_ids, allocated, id_count + 1))
+ return log_oom();
+
+ id = &all_ids[id_count];
+
+ r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
+ if (r < 0) {
+ continue;
+ }
+
+ sd_journal_flush_matches(j);
+ r = sd_journal_add_match(j, data, length);
+ if (r < 0)
+ continue;
+
+ r = sd_journal_seek_head(j);
+ if (r < 0)
+ continue;
+
+ r = sd_journal_next(j);
+ if (r <= 0)
+ continue;
+
+ r = sd_journal_get_realtime_usec(j, &id->timestamp);
+ if (r < 0)
+ continue;
+
+ if (!find_first_boot && sd_id128_equal(id->id, *boot_id)) {
+ ref_boot_id = *id;
+ ref_boot_found = true;
+ }
+
+ id_count++;
+ }
+
+ *boot_id = SD_ID128_NULL;
+ sd_journal_flush_matches(j);
+
+ if (id_count == 0 || (!find_first_boot && !ref_boot_found))
+ return 0;
+
+ qsort(all_ids, id_count, sizeof(boot_id_t), boot_id_cmp);
+ if (find_first_boot)
+ id = all_ids;
+ else
+ id = bsearch(&ref_boot_id, all_ids, id_count, sizeof(boot_id_t), boot_id_cmp);
+
+ if (!id || (relative < 0 && ((id - all_ids) + relative) < 0) ||
+ (relative >= 0 && (unsigned long)((id - all_ids) + relative) >= id_count))
+ return 0;
+
+ id += relative;
+ *boot_id = id->id;
+ return 0;
+}
+
+static int add_boot(sd_journal *j) {