-int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) {
- uint64_t p, osize, hash, h;
- int r;
-
- assert(f);
- assert(data || size == 0);
-
- osize = offsetof(Object, data.payload) + size;
-
- hash = hash64(data, size);
- h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem));
- p = le64toh(f->hash_table[h].head_hash_offset);
-
- while (p != 0) {
- Object *o;
-
- r = journal_file_move_to_object(f, p, &o);
- if (r < 0)
- return r;
-
- if (le64toh(o->object.type) != OBJECT_DATA)
- return -EBADMSG;
-
- if (le64toh(o->object.size) == osize &&
- memcmp(o->data.payload, data, size) == 0) {
-
- if (le64toh(o->data.hash) != hash)
- return -EBADMSG;
-
- if (o->data.head_entry_offset == 0)
- return 0;
-
- p = le64toh(o->data.head_entry_offset);
- r = journal_file_move_to_object(f, p, &o);
- if (r < 0)
- return r;
-
- if (le64toh(o->object.type) != OBJECT_ENTRY)
- return -EBADMSG;
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = p;
-
- return 1;
- }
-
- p = le64toh(o->data.next_hash_offset);
- }
-
- return 0;
-}
-
-int journal_file_find_last_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) {
- uint64_t p, osize, hash, h;
- int r;
-
- assert(f);
- assert(data || size == 0);
-
- osize = offsetof(Object, data.payload) + size;
-
- hash = hash64(data, size);
- h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem));
- p = le64toh(f->hash_table[h].tail_hash_offset);
-
- while (p != 0) {
- Object *o;
-
- r = journal_file_move_to_object(f, p, &o);
- if (r < 0)
- return r;
-
- if (le64toh(o->object.type) != OBJECT_DATA)
- return -EBADMSG;
-
- if (le64toh(o->object.size) == osize &&
- memcmp(o->data.payload, data, size) == 0) {
-
- if (le64toh(o->data.hash) != hash)
- return -EBADMSG;
-
- if (o->data.tail_entry_offset == 0)
- return 0;
-
- p = le64toh(o->data.tail_entry_offset);
- r = journal_file_move_to_object(f, p, &o);
- if (r < 0)
- return r;
-
- if (le64toh(o->object.type) != OBJECT_ENTRY)
- return -EBADMSG;
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = p;
-
- return 1;
- }
-
- p = le64toh(o->data.prev_hash_offset);
- }
-
- return 0;
-}
-
-void journal_file_dump(JournalFile *f) {
- char a[33], b[33], c[33];
- Object *o;
- int r;
- uint64_t p;
-
- assert(f);
-
- printf("File ID: %s\n"
- "Machine ID: %s\n"
- "Boot ID: %s\n"
- "Arena size: %llu\n",
- sd_id128_to_string(f->header->file_id, a),
- sd_id128_to_string(f->header->machine_id, b),
- sd_id128_to_string(f->header->boot_id, c),
- (unsigned long long) le64toh(f->header->arena_size));
-
- p = le64toh(f->header->head_object_offset);
- while (p != 0) {
- r = journal_file_move_to_object(f, p, &o);
- if (r < 0)
- goto fail;
-
- switch (o->object.type) {
-
- case OBJECT_UNUSED:
- printf("Type: OBJECT_UNUSED\n");
- break;
-
- case OBJECT_DATA:
- printf("Type: OBJECT_DATA\n");
- break;
-
- case OBJECT_ENTRY:
- printf("Type: OBJECT_ENTRY %llu\n", (unsigned long long) le64toh(o->entry.seqnum));
- break;
-
- case OBJECT_HASH_TABLE:
- printf("Type: OBJECT_HASH_TABLE\n");
- break;
-
- case OBJECT_BISECT_TABLE:
- printf("Type: OBJECT_BISECT_TABLE\n");
- break;
- }
-
- if (p == le64toh(f->header->tail_object_offset))
- p = 0;
- else
- p = p + ALIGN64(le64toh(o->object.size));
- }
-
- return;
-fail:
- log_error("File corrupt");
-}
-
-int journal_file_open(
- const char *fname,
- int flags,
- mode_t mode,
- JournalFile **ret) {
-
- JournalFile *f;
- int r;
- bool newly_created = false;
-
- assert(fname);
-
- if ((flags & O_ACCMODE) != O_RDONLY &&
- (flags & O_ACCMODE) != O_RDWR)
- return -EINVAL;
-
- f = new0(JournalFile, 1);
- if (!f)
- return -ENOMEM;
-
- f->writable = (flags & O_ACCMODE) != O_RDONLY;
- f->prot = prot_from_flags(flags);
-
- f->fd = open(fname, flags|O_CLOEXEC, mode);
- if (f->fd < 0) {
- r = -errno;
- goto fail;
- }
-
- f->path = strdup(fname);
- if (!f->path) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (fstat(f->fd, &f->last_stat) < 0) {
- r = -errno;
- goto fail;
- }
-
- if (f->last_stat.st_size == 0 && f->writable) {
- newly_created = true;
-
- r = journal_file_init_header(f);
- if (r < 0)
- goto fail;
-
- if (fstat(f->fd, &f->last_stat) < 0) {
- r = -errno;
- goto fail;
- }
- }
-
- if (f->last_stat.st_size < (off_t) sizeof(Header)) {
- r = -EIO;
- goto fail;
- }
-
- f->header = mmap(NULL, PAGE_ALIGN(sizeof(Header)), prot_from_flags(flags), MAP_SHARED, f->fd, 0);
- if (f->header == MAP_FAILED) {
- f->header = NULL;
- r = -errno;
- goto fail;
- }
-
- if (!newly_created) {
- r = journal_file_verify_header(f);
- if (r < 0)
- goto fail;
- }
-
- if (f->writable) {
- r = journal_file_refresh_header(f);
- if (r < 0)
- goto fail;
- }
-
- if (newly_created) {
-
- r = journal_file_setup_hash_table(f);
- if (r < 0)
- goto fail;
-
- r = journal_file_setup_bisect_table(f);
- if (r < 0)
- goto fail;
- }
-
- r = journal_file_map_hash_table(f);
- if (r < 0)
- goto fail;
-
- r = journal_file_map_bisect_table(f);
- if (r < 0)
- goto fail;
-
- if (ret)
- *ret = f;
-
- return 0;
-
-fail:
- journal_file_close(f);
-
- return r;