journal-verify.c revision 369f0589218a874a88bc69c5481d8f90f987b7dd
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2012 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/mman.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <fcntl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <stddef.h>
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering#include "util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "macro.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "journal-def.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "journal-file.h"
96aad8d15a324d0e956a4e5653a11a67b209b41aLennart Poettering#include "journal-authenticate.h"
23c80348e656a4e6fd9ba8f17523a65b6fa349a0Kay Sievers#include "journal-verify.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "lookup3.h"
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering#include "compress.h"
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering#include "fsprg.h"
003dffde2c1b93afbc9aff24b277276f65424406Lennart Poettering
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poetteringstatic int journal_file_object_verify(JournalFile *f, Object *o) {
003dffde2c1b93afbc9aff24b277276f65424406Lennart Poettering uint64_t i;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
003dffde2c1b93afbc9aff24b277276f65424406Lennart Poettering assert(f);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(o);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering /* This does various superficial tests about the length an
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering * possible field values. It does not follow any references to
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering * other objects. */
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if ((o->object.flags & OBJECT_COMPRESSED) &&
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering o->object.type != OBJECT_DATA)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering switch (o->object.type) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering case OBJECT_DATA: {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering uint64_t h1, h2;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (le64toh(o->data.entry_offset) <= 0 ||
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering le64toh(o->data.n_entries) <= 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering h1 = le64toh(o->data.hash);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (o->object.flags & OBJECT_COMPRESSED) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering void *b = NULL;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering uint64_t alloc = 0, b_size;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (!uncompress_blob(o->data.payload,
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering le64toh(o->object.size) - offsetof(Object, data.payload),
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering &b, &alloc, &b_size))
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering h2 = hash64(b, b_size);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering free(b);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering } else
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (h1 != h2)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
cb81cd8073392936882643af0129934bf67e96c4Lennart Poettering if (!VALID64(o->data.next_hash_offset) ||
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering !VALID64(o->data.next_field_offset) ||
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering !VALID64(o->data.entry_offset) ||
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering !VALID64(o->data.entry_array_offset))
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering break;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering }
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering case OBJECT_FIELD:
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (!VALID64(o->field.next_hash_offset) ||
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering !VALID64(o->field.head_data_offset))
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering break;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering case OBJECT_ENTRY:
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (le64toh(o->entry.seqnum) <= 0 ||
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering !VALID_REALTIME(le64toh(o->entry.realtime)) ||
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering !VALID_MONOTONIC(le64toh(o->entry.monotonic)))
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering for (i = 0; i < journal_file_entry_n_items(o); i++) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (o->entry.items[i].object_offset == 0 ||
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering !VALID64(o->entry.items[i].object_offset))
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering }
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
cb81cd8073392936882643af0129934bf67e96c4Lennart Poettering break;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering case OBJECT_DATA_HASH_TABLE:
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering case OBJECT_FIELD_HASH_TABLE:
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EBADMSG;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering for (i = 0; i < journal_file_hash_table_n_items(o); i++) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (o->hash_table.items[i].head_hash_offset != 0 &&
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering !VALID64(le64toh(o->hash_table.items[i].head_hash_offset)))
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -EBADMSG;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (o->hash_table.items[i].tail_hash_offset != 0 &&
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering !VALID64(le64toh(o->hash_table.items[i].tail_hash_offset)))
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -EBADMSG;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((o->hash_table.items[i].head_hash_offset != 0) !=
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering (o->hash_table.items[i].tail_hash_offset != 0))
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -EBADMSG;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering break;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering case OBJECT_ENTRY_ARRAY:
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return -EBADMSG;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -EBADMSG;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!VALID64(o->entry_array.next_entry_array_offset))
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering return -EBADMSG;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering for (i = 0; i < journal_file_entry_array_n_items(o); i++)
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (o->entry_array.items[i] != 0 &&
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering !VALID64(o->entry_array.items[i]))
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return -EBADMSG;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering break;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering case OBJECT_TAG:
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering if (le64toh(o->object.size) != sizeof(TagObject))
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return -EBADMSG;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering if (!VALID_EPOCH(o->tag.epoch))
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return -EBADMSG;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering break;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering }
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return 0;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering}
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poetteringstatic void draw_progress(uint64_t p, usec_t *last_usec) {
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering unsigned n, i, j, k;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering usec_t z, x;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering if (!isatty(STDOUT_FILENO))
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering z = now(CLOCK_MONOTONIC);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering x = *last_usec;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (x != 0 && x + 40 * USEC_PER_MSEC > z)
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering return;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering *last_usec = z;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering n = (3 * columns()) / 4;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering j = (n * (unsigned) p) / 65535ULL;
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering k = n - j;
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fputs("\r\x1B[?25l" ANSI_HIGHLIGHT_GREEN_ON, stdout);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering for (i = 0; i < j; i++)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fputs("\xe2\x96\x88", stdout);
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering fputs(ANSI_HIGHLIGHT_OFF, stdout);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering for (i = 0; i < k; i++)
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering fputs("\xe2\x96\x91", stdout);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering printf(" %3lu%%", 100LU * (unsigned long) p / 65535LU);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering fputs("\r\x1B[?25h", stdout);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fflush(stdout);
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering}
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic void flush_progress(void) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering unsigned n, i;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!isatty(STDOUT_FILENO))
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek return;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering n = (3 * columns()) / 4;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering putchar('\r');
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering for (i = 0; i < n + 5; i++)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering putchar(' ');
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering putchar('\r');
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fflush(stdout);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int write_uint64(int fd, uint64_t p) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering ssize_t k;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering k = write(fd, &p, sizeof(p));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (k < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -errno;
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering if (k != sizeof(p))
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -EIO;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringstatic int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering uint64_t a, b;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering int r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(m);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(fd >= 0);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering /* Bisection ... */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering a = 0; b = n;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering while (a < b) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering uint64_t c, *z;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering c = (a + b) / 2;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, c * sizeof(uint64_t), sizeof(uint64_t), (void **) &z);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (*z == p)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return 1;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
9030ca462bd13cd6536299814e4a71d5c5e85be9Lennart Poettering if (a + 1 >= b)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (p < *z)
8aec412ff697bc14995746953912ca6fdf2c9ba8Lennart Poettering b = c;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering a = c;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int entry_points_to_data(
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering JournalFile *f,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering int entry_fd,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering uint64_t n_entries,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t entry_p,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering uint64_t data_p) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering int r;
7f0d207d2c816e0a8cb2742b0a789911f7c99356Lennart Poettering uint64_t i, n, a;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering Object *o;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool found = false;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(f);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering assert(entry_fd >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Data object references invalid entry at %llu", (unsigned long long) data_p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EBADMSG;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, entry_p, &o);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering n = journal_file_entry_n_items(o);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering for (i = 0; i < n; i++)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (le64toh(o->entry.items[i].object_offset) == data_p) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering found = true;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering break;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering }
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (!found) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering log_error("Data object not referenced by linked entry at %llu", (unsigned long long) data_p);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return -EBADMSG;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering }
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* Check if this entry is also in main entry array. Since the
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering * main entry array has already been verified we can rely on
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering * its consistency.*/
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering i = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering n = le64toh(f->header->n_entries);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering a = le64toh(f->header->entry_array_offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (i < n) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering uint64_t m, u;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering m = journal_file_entry_array_n_items(o);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering u = MIN(n - i, m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (entry_p <= le64toh(o->entry_array.items[u-1])) {
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering uint64_t x, y, z;
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering x = 0;
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering y = u;
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering while (x < y) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering z = (x + y) / 2;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering if (le64toh(o->entry_array.items[z]) == entry_p)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (x + 1 >= y)
554604b3073467af75dc94fac9e2343148603289Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (entry_p < le64toh(o->entry_array.items[z]))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering y = z;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering x = z;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Entry object doesn't exist in main entry array at %llu", (unsigned long long) entry_p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EBADMSG;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering i += u;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering a = le64toh(o->entry_array.next_entry_array_offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int verify_data(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering JournalFile *f,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Object *o, uint64_t p,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int entry_fd, uint64_t n_entries,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering int entry_array_fd, uint64_t n_entry_arrays) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t i, n, a, last, q;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering assert(f);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering assert(o);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering assert(entry_fd >= 0);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering assert(entry_array_fd >= 0);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering n = le64toh(o->data.n_entries);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering a = le64toh(o->data.entry_array_offset);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* We already checked this earlier */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering assert(n > 0);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering last = q = le64toh(o->data.entry_offset);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = entry_points_to_data(f, entry_fd, n_entries, q, p);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (r < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering i = 1;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering while (i < n) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering uint64_t next, m, j;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (a == 0) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering log_error("Array chain too short at %llu", (unsigned long long) p);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return -EBADMSG;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering log_error("Invalid array at %llu", (unsigned long long) p);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering return -EBADMSG;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (r < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering next = le64toh(o->entry_array.next_entry_array_offset);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (next != 0 && next <= a) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering log_error("Array chain has cycle at %llu", (unsigned long long) p);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return -EBADMSG;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering m = journal_file_entry_array_n_items(o);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering for (j = 0; i < n && j < m; i++, j++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering q = le64toh(o->entry_array.items[j]);
a3e7f417d72ba3251fd6b3a228a2721a4b725a03Zbigniew Jędrzejewski-Szmek if (q <= last) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering log_error("Data object's entry array not sorted at %llu", (unsigned long long) p);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return -EBADMSG;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering last = q;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = entry_points_to_data(f, entry_fd, n_entries, q, p);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (r < 0)
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering return r;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* Pointer might have moved, reposition */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (r < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering a = next;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering }
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering return 0;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering}
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringstatic int verify_hash_table(
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering JournalFile *f,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering int data_fd, uint64_t n_data,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering int entry_fd, uint64_t n_entries,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering int entry_array_fd, uint64_t n_entry_arrays,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering usec_t *last_usec,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering bool show_progress) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering uint64_t i, n;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering int r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(f);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(data_fd >= 0);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(entry_fd >= 0);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(entry_array_fd >= 0);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(last_usec);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering for (i = 0; i < n; i++) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering uint64_t last = 0, p;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (show_progress)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering draw_progress(0xC000 + (0x3FFF * i / n), last_usec);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering p = le64toh(f->data_hash_table[i].head_hash_offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (p != 0) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering Object *o;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering uint64_t next;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (!contains_uint64(f->mmap, data_fd, n_data, p)) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering log_error("Invalid data object at hash entry %llu of %llu",
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering (unsigned long long) i, (unsigned long long) n);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return -EBADMSG;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering }
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering next = le64toh(o->data.next_hash_offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (next != 0 && next <= p) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Hash chain has a cycle in hash entry %llu of %llu",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (unsigned long long) i, (unsigned long long) n);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -EBADMSG;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (le64toh(o->data.hash) % n != i) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_error("Hash value mismatch in hash entry %llu of %llu",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering (unsigned long long) i, (unsigned long long) n);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return -EBADMSG;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = verify_data(f, o, p, entry_fd, n_entries, entry_array_fd, n_entry_arrays);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering last = p;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering p = next;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (last != le64toh(f->data_hash_table[i].tail_hash_offset)) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_error("Tail hash pointer mismatch in hash table");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EBADMSG;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringstatic int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t n, h, q;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering int r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(f);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering h = hash % n;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering q = le64toh(f->data_hash_table[h].head_hash_offset);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering while (q != 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering Object *o;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (p == q)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return 1;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = journal_file_move_to_object(f, OBJECT_DATA, q, &o);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering q = le64toh(o->data.next_hash_offset);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poetteringstatic int verify_entry(
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering JournalFile *f,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering Object *o, uint64_t p,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering int data_fd, uint64_t n_data) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering uint64_t i, n;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering int r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(f);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(o);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(data_fd >= 0);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering n = journal_file_entry_n_items(o);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering for (i = 0; i < n; i++) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering uint64_t q, h;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering Object *u;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering q = le64toh(o->entry.items[i].object_offset);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering h = le64toh(o->entry.items[i].hash);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (!contains_uint64(f->mmap, data_fd, n_data, q)) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_error("Invalid data object at entry %llu",
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering (unsigned long long) p);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -EBADMSG;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = journal_file_move_to_object(f, OBJECT_DATA, q, &u);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (r < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (le64toh(u->data.hash) != h) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_error("Hash mismatch for data object at entry %llu",
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering (unsigned long long) p);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -EBADMSG;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = data_object_in_hash_table(f, h, q);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (r < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (r == 0) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_error("Data object missing from hash at entry %llu",
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering (unsigned long long) p);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -EBADMSG;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return 0;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int verify_entry_array(
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering JournalFile *f,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int data_fd, uint64_t n_data,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int entry_fd, uint64_t n_entries,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int entry_array_fd, uint64_t n_entry_arrays,
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering usec_t *last_usec,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering bool show_progress) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering uint64_t i = 0, a, n, last = 0;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering int r;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering assert(f);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(data_fd >= 0);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(entry_fd >= 0);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(entry_array_fd >= 0);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(last_usec);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering n = le64toh(f->header->n_entries);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering a = le64toh(f->header->entry_array_offset);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering while (i < n) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering uint64_t next, m, j;
9030ca462bd13cd6536299814e4a71d5c5e85be9Lennart Poettering Object *o;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (show_progress)
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering draw_progress(0x8000 + (0x3FFF * i / n), last_usec);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering if (a == 0) {
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering log_error("Array chain too short at %llu of %llu",
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering (unsigned long long) i, (unsigned long long) n);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering return -EBADMSG;
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering }
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering log_error("Invalid array at %llu of %llu",
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering (unsigned long long) i, (unsigned long long) n);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering return -EBADMSG;
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering }
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering if (r < 0)
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering return r;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering next = le64toh(o->entry_array.next_entry_array_offset);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering if (next != 0 && next <= a) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering log_error("Array chain has cycle at %llu of %llu",
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering (unsigned long long) i, (unsigned long long) n);
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering return -EBADMSG;
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering }
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering m = journal_file_entry_array_n_items(o);
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering for (j = 0; i < n && j < m; i++, j++) {
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering uint64_t p;
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering p = le64toh(o->entry_array.items[j]);
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering if (p <= last) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering log_error("Entry array not sorted at %llu of %llu",
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering (unsigned long long) i, (unsigned long long) n);
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering return -EBADMSG;
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering }
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering last = p;
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) {
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering log_error("Invalid array entry at %llu of %llu",
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering (unsigned long long) i, (unsigned long long) n);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering return -EBADMSG;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering }
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering if (r < 0)
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering return r;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering r = verify_entry(f, o, p, data_fd, n_data);
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering if (r < 0)
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering return r;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering /* Pointer might have moved, reposition */
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering if (r < 0)
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering return r;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering }
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering a = next;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering }
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering return 0;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering}
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poetteringint journal_file_verify(
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering JournalFile *f,
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering const char *key,
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering usec_t *first_validated, usec_t *last_validated, usec_t *last_contained,
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering bool show_progress) {
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering int r;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering Object *o;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering sd_id128_t entry_boot_id;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering usec_t last_usec = 0;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering char data_path[] = "/var/tmp/journal-data-XXXXXX",
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering entry_path[] = "/var/tmp/journal-entry-XXXXXX",
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering entry_array_path[] = "/var/tmp/journal-entry-array-XXXXXX";
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering unsigned i;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering bool found_last;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering assert(f);
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (key) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering#ifdef HAVE_GCRYPT
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering r = journal_file_parse_verification_key(f, key);
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (r < 0) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering log_error("Failed to parse seed.");
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering return r;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering }
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering#else
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering return -ENOTSUP;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering#endif
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering } else if (f->seal)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering return -ENOKEY;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering data_fd = mkostemp(data_path, O_CLOEXEC);
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (data_fd < 0) {
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering log_error("Failed to create data file: %m");
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering r = -errno;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering goto fail;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering }
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering unlink(data_path);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering entry_fd = mkostemp(entry_path, O_CLOEXEC);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (entry_fd < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_error("Failed to create entry file: %m");
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = -errno;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering goto fail;
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering unlink(entry_path);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering entry_array_fd = mkostemp(entry_array_path, O_CLOEXEC);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (entry_array_fd < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_error("Failed to create entry array file: %m");
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = -errno;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering goto fail;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering unlink(entry_array_path);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering#ifdef HAVE_GCRYPT
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) != 0)
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering#else
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (f->header->compatible_flags != 0)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering#endif
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering log_error("Cannot verify file with unknown extensions.");
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = -ENOTSUP;
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering goto fail;
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering for (i = 0; i < sizeof(f->header->reserved); i++)
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (f->header->reserved[i] != 0) {
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering log_error("Reserved field in non-zero.");
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = -EBADMSG;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering goto fail;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering /* First iteration: we go through all objects, verify the
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * superficial structure, headers, hashes. */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering p = le64toh(f->header->header_size);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering while (p != 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (show_progress)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering r = journal_file_move_to_object(f, -1, p, &o);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (r < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_error("Invalid object at %llu", (unsigned long long) p);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering goto fail;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (p > le64toh(f->header->tail_object_offset)) {
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering log_error("Invalid tail object pointer");
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = -EBADMSG;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering goto fail;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering }
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (p == le64toh(f->header->tail_object_offset))
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering found_last = true;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering n_objects ++;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = journal_file_object_verify(f, o);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (r < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_error("Invalid object contents at %llu", (unsigned long long) p);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering goto fail;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if ((o->object.flags & OBJECT_COMPRESSED) && !JOURNAL_HEADER_COMPRESSED(f->header)) {
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering log_error("Compressed object in file without compression at %llu", (unsigned long long) p);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering r = -EBADMSG;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering goto fail;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering switch (o->object.type) {
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering case OBJECT_DATA:
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering r = write_uint64(data_fd, p);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (r < 0)
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering goto fail;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering n_data++;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering break;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering case OBJECT_FIELD:
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering n_fields++;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering break;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering case OBJECT_ENTRY:
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) {
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering log_error("First entry before first tag at %llu", (unsigned long long) p);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering r = -EBADMSG;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering goto fail;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering }
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering r = write_uint64(entry_fd, p);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering if (r < 0)
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering goto fail;
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering if (le64toh(o->entry.realtime) < last_tag_realtime) {
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering log_error("Older entry after newer tag at %llu", (unsigned long long) p);
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering r = -EBADMSG;
26166c88e0b47b83972f32b5057ecbffe06bf904Lennart Poettering goto fail;
26166c88e0b47b83972f32b5057ecbffe06bf904Lennart Poettering }
26166c88e0b47b83972f32b5057ecbffe06bf904Lennart Poettering
26166c88e0b47b83972f32b5057ecbffe06bf904Lennart Poettering if (!entry_seqnum_set &&
efe0286285a7432f738fafae840fa4eda51c2986Lennart Poettering le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) {
efe0286285a7432f738fafae840fa4eda51c2986Lennart Poettering log_error("Head entry sequence number incorrect at %llu", (unsigned long long) p);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering r = -EBADMSG;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering goto fail;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering }
26166c88e0b47b83972f32b5057ecbffe06bf904Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering if (entry_seqnum_set &&
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering entry_seqnum >= le64toh(o->entry.seqnum)) {
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering log_error("Entry sequence number out of synchronization at %llu", (unsigned long long) p);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering r = -EBADMSG;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering goto fail;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering }
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering entry_seqnum = le64toh(o->entry.seqnum);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering entry_seqnum_set = true;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (entry_monotonic_set &&
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering sd_id128_equal(entry_boot_id, o->entry.boot_id) &&
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering entry_monotonic > le64toh(o->entry.monotonic)) {
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering log_error("Entry timestamp out of synchronization at %llu", (unsigned long long) p);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering r = -EBADMSG;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering goto fail;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering }
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering entry_monotonic = le64toh(o->entry.monotonic);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering entry_boot_id = o->entry.boot_id;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering entry_monotonic_set = true;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering if (!entry_realtime_set &&
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) {
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering log_error("Head entry realtime timestamp incorrect");
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering r = -EBADMSG;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering goto fail;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering }
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering entry_realtime = le64toh(o->entry.realtime);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering entry_realtime_set = true;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_entries ++;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering break;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering case OBJECT_DATA_HASH_TABLE:
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (n_data_hash_tables > 1) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("More than one data hash table at %llu", (unsigned long long) p);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) ||
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Header fields for data hash table invalid");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_data_hash_tables++;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering break;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering case OBJECT_FIELD_HASH_TABLE:
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (n_field_hash_tables > 1) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("More than one field hash table at %llu", (unsigned long long) p);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) ||
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Header fields for field hash table invalid");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_field_hash_tables++;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering break;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering case OBJECT_ENTRY_ARRAY:
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = write_uint64(entry_array_fd, p);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (r < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (p == le64toh(f->header->entry_array_offset)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (found_main_entry_array) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("More than one main entry array at %llu", (unsigned long long) p);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering found_main_entry_array = true;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_entry_arrays++;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering break;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering case OBJECT_TAG:
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (!JOURNAL_HEADER_SEALED(f->header)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Tag object in file without sealing at %llu", (unsigned long long) p);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (le64toh(o->tag.seqnum) != n_tags + 1) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (le64toh(o->tag.epoch) < last_epoch) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Epoch sequence out of synchronization at %llu", (unsigned long long) p);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering#ifdef HAVE_GCRYPT
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (f->seal) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering uint64_t q, rt;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum));
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Tag/entry realtime timestamp out of synchronization at %llu", (unsigned long long) p);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering /* OK, now we know the epoch. So let's now set
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering * it, and calculate the HMAC for everything
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering * since the last tag. */
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch));
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (r < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = journal_file_hmac_start(f);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (r < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (last_tag == 0) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = journal_file_hmac_put_header(f);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (r < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering q = le64toh(f->header->header_size);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering } else
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering q = last_tag;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering while (q <= p) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = journal_file_move_to_object(f, -1, q, &o);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (r < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = journal_file_hmac_put_object(f, -1, q);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (r < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering q = q + ALIGN64(le64toh(o->object.size));
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering /* Position might have changed, let's reposition things */
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = journal_file_move_to_object(f, -1, p, &o);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (r < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Tag failed verification at %llu", (unsigned long long) p);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering f->hmac_running = false;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering last_tag_realtime = rt;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering last_sealed_realtime = entry_realtime;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering#endif
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering last_tag = p + ALIGN64(le64toh(o->object.size));
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering last_epoch = le64toh(o->tag.epoch);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_tags ++;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering break;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering default:
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_weird ++;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (p == le64toh(f->header->tail_object_offset))
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering p = 0;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering else
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering p = p + ALIGN64(le64toh(o->object.size));
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (!found_last) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Tail object pointer dead");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (n_objects != le64toh(f->header->n_objects)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Object number mismatch");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (n_entries != le64toh(f->header->n_entries)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Entry number mismatch");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (JOURNAL_HEADER_CONTAINS(f->header, n_data) &&
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_data != le64toh(f->header->n_data)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Data number mismatch");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) &&
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_fields != le64toh(f->header->n_fields)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Field number mismatch");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) &&
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_tags != le64toh(f->header->n_tags)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Tag number mismatch");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) &&
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_entry_arrays != le64toh(f->header->n_entry_arrays)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Entry array number mismatch");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (n_data_hash_tables != 1) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Missing data hash table");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (n_field_hash_tables != 1) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Missing field hash table");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (!found_main_entry_array) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Missing entry array");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (entry_seqnum_set &&
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering entry_seqnum != le64toh(f->header->tail_entry_seqnum)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("Invalid tail seqnum");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = -EBADMSG;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (entry_monotonic_set &&
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering (!sd_id128_equal(entry_boot_id, f->header->boot_id) ||
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering entry_monotonic != le64toh(f->header->tail_entry_monotonic))) {
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering log_error("Invalid tail monotonic timestamp");
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering r = -EBADMSG;
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering goto fail;
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering }
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering log_error("Invalid tail realtime timestamp");
8d07a7c47159ebc2bcc775e2c1997cb44bd1ac95Lennart Poettering r = -EBADMSG;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering goto fail;
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering }
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering
3a6fb33c54bc64398e0af1c9d7c74a6b614a849dLennart Poettering /* Second iteration: we follow all objects referenced from the
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * two entry points: the object hash table and the entry
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering * array. We also check that everything referenced (directly
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering * or indirectly) in the data hash table also exists in the
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering * entry array, and vice versa. Note that we do not care for
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering * unreferenced objects. We only care that everything that is
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering * referenced is consistent. */
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering r = verify_entry_array(f,
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering data_fd, n_data,
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering entry_fd, n_entries,
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering entry_array_fd, n_entry_arrays,
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering &last_usec,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering show_progress);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (r < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering goto fail;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = verify_hash_table(f,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering data_fd, n_data,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering entry_fd, n_entries,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering entry_array_fd, n_entry_arrays,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &last_usec,
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering show_progress);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (show_progress)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering flush_progress();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mmap_cache_close_fd(f->mmap, data_fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering mmap_cache_close_fd(f->mmap, entry_fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mmap_cache_close_fd(f->mmap, entry_array_fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering close_nointr_nofail(data_fd);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering close_nointr_nofail(entry_fd);
65d73cf042ba7de11d254f5c4714f467db64b7c3Lennart Poettering close_nointr_nofail(entry_array_fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering if (first_validated)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering *first_validated = last_tag_realtime ? le64toh(f->header->head_entry_realtime) : 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (last_validated)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering *last_validated = last_sealed_realtime;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering if (last_contained)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering *last_contained = le64toh(f->header->tail_entry_realtime);
491ac9f2c4aeda8c40edde35112404b737e38b60Lennart Poettering
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringfail:
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (show_progress)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering flush_progress();
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering log_error("File corruption detected at %s:%llu (of %llu, %llu%%).",
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering f->path,
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering (unsigned long long) p,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering (unsigned long long) f->last_stat.st_size,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering (unsigned long long) (100 * p / f->last_stat.st_size));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (data_fd >= 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mmap_cache_close_fd(f->mmap, data_fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(data_fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (entry_fd >= 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mmap_cache_close_fd(f->mmap, entry_fd);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering close_nointr_nofail(entry_fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (entry_array_fd >= 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering mmap_cache_close_fd(f->mmap, entry_array_fd);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering close_nointr_nofail(entry_array_fd);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering