|
| 1 | +/* |
| 2 | +
|
| 3 | + File: file_journal.c |
| 4 | +
|
| 5 | + Copyright (C) 2025 Christophe GRENIER <[email protected]> |
| 6 | +
|
| 7 | + This software is free software; you can redistribute it and/or modify |
| 8 | + it under the terms of the GNU General Public License as published by |
| 9 | + the Free Software Foundation; either version 2 of the License, or |
| 10 | + (at your option) any later version. |
| 11 | +
|
| 12 | + This program is distributed in the hope that it will be useful, |
| 13 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + GNU General Public License for more details. |
| 16 | +
|
| 17 | + You should have received a copy of the GNU General Public License along |
| 18 | + with this program; if not, write the Free Software Foundation, Inc., 51 |
| 19 | + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | +
|
| 21 | + */ |
| 22 | + |
| 23 | +#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_journal) |
| 24 | +#ifdef HAVE_CONFIG_H |
| 25 | +#include <config.h> |
| 26 | +#endif |
| 27 | +#ifdef HAVE_STRING_H |
| 28 | +#include <string.h> |
| 29 | +#endif |
| 30 | +#include <stdio.h> |
| 31 | +#include "types.h" |
| 32 | +#include "filegen.h" |
| 33 | +#include "common.h" |
| 34 | + |
| 35 | +/*@ requires valid_register_header_check(file_stat); */ |
| 36 | +static void register_header_check_journal(file_stat_t *file_stat); |
| 37 | + |
| 38 | +const file_hint_t file_hint_journal= { |
| 39 | + .extension="journal", |
| 40 | + .description="Systemd journal", |
| 41 | + .max_filesize=PHOTOREC_MAX_FILE_SIZE, |
| 42 | + .recover=1, |
| 43 | + .enable_by_default=1, |
| 44 | + .register_header_check=®ister_header_check_journal |
| 45 | +}; |
| 46 | + |
| 47 | +typedef union sd_id128 { |
| 48 | + uint8_t bytes[16]; |
| 49 | + uint64_t qwords[2]; |
| 50 | +} sd_id128_t; |
| 51 | + |
| 52 | +struct header_journal |
| 53 | +{ |
| 54 | + uint8_t signature[8]; |
| 55 | + uint32_t compatible_flags; |
| 56 | + uint32_t incompatible_flags; |
| 57 | + uint8_t state; |
| 58 | + uint8_t reserved[7]; |
| 59 | + sd_id128_t file_id; |
| 60 | + sd_id128_t machine_id; |
| 61 | + sd_id128_t tail_entry_boot_id; |
| 62 | + sd_id128_t seqnum_id; |
| 63 | + uint64_t header_size; |
| 64 | + uint64_t arena_size; |
| 65 | + uint64_t data_hash_table_offset; |
| 66 | + uint64_t data_hash_table_size; |
| 67 | + uint64_t field_hash_table_offset; |
| 68 | + uint64_t field_hash_table_size; |
| 69 | + uint64_t tail_object_offset; |
| 70 | + uint64_t n_objects; |
| 71 | + uint64_t n_entries; |
| 72 | + uint64_t tail_entry_seqnum; |
| 73 | + uint64_t head_entry_seqnum; |
| 74 | + uint64_t entry_array_offset; |
| 75 | + uint64_t head_entry_realtime; |
| 76 | + uint64_t tail_entry_realtime; |
| 77 | + uint64_t tail_entry_monotonic; |
| 78 | + /* Added in 187 */ |
| 79 | + uint64_t n_data; |
| 80 | + uint64_t n_fields; |
| 81 | + /* Added in 189 */ |
| 82 | + uint64_t n_tags; |
| 83 | + uint64_t n_entry_arrays; |
| 84 | + /* Added in 246 */ |
| 85 | + uint64_t data_hash_chain_depth; |
| 86 | + uint64_t field_hash_chain_depth; |
| 87 | + /* Added in 252 */ |
| 88 | + uint32_t tail_entry_array_offset; |
| 89 | + uint32_t tail_entry_array_n_entries; |
| 90 | + /* Added in 254 */ |
| 91 | + uint64_t tail_entry_offset; |
| 92 | +}; |
| 93 | + |
| 94 | +/*@ |
| 95 | + @ requires valid_header_check_param(buffer, buffer_size, safe_header_only, file_recovery, file_recovery_new); |
| 96 | + @ ensures valid_header_check_result(\result, file_recovery_new); |
| 97 | + @*/ |
| 98 | +static int header_check_journal(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) |
| 99 | +{ |
| 100 | + const struct header_journal *h=(const struct header_journal *)buffer; |
| 101 | + const uint64_t header_size=le64(h->header_size); |
| 102 | + if(header_size < 272) |
| 103 | + return 0; |
| 104 | + if(buffer[9]!=0 || buffer[10]!=0 || buffer[11]!=0) |
| 105 | + return 0; |
| 106 | + reset_file_recovery(file_recovery_new); |
| 107 | + file_recovery_new->extension=file_hint_journal.extension; |
| 108 | + file_recovery_new->min_filesize=header_size; |
| 109 | + return 1; |
| 110 | +} |
| 111 | + |
| 112 | +static void register_header_check_journal(file_stat_t *file_stat) |
| 113 | +{ |
| 114 | + static const unsigned char journal_header[8]= { |
| 115 | + 'L' , 'P' , 'K' , 'S' , 'H' , 'H' , 'R' , 'H' , |
| 116 | + }; |
| 117 | + register_header_check(0, journal_header, sizeof(journal_header), &header_check_journal, file_stat); |
| 118 | +} |
| 119 | +#endif |
0 commit comments