Skip to content

Commit a3ad131

Browse files
committed
src/file_journal.c: recover Systemd journal files
1 parent 00a9998 commit a3ad131

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ file_C = filegen.c \
214214
file_it.c \
215215
file_itu.c \
216216
file_jks.c \
217+
file_journal.c \
217218
file_jpg.c \
218219
file_jsonlz4.c \
219220
file_kdb.c \

src/file_journal.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
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=&register_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

src/file_list.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ extern const file_hint_t file_hint_itunes;
524524
extern const file_hint_t file_hint_jks;
525525
#endif
526526
#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_jpg)
527+
extern const file_hint_t file_hint_journal;
527528
extern const file_hint_t file_hint_jpg;
528529
#endif
529530
#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_jsonlz4)
@@ -1580,6 +1581,7 @@ file_enable_t array_file_enable[]=
15801581
{ .enable=0, .file_hint=&file_hint_jks },
15811582
#endif
15821583
#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_jpg)
1584+
{ .enable=0, .file_hint=&file_hint_journal },
15831585
{ .enable=0, .file_hint=&file_hint_jpg },
15841586
#endif
15851587
#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_jsonlz4)

0 commit comments

Comments
 (0)