libaaruformat
1.0
Aaru Data Preservation Suite - Format Library
Toggle main menu visibility
Loading...
Searching...
No Matches
index_v1.c
Go to the documentation of this file.
1
/*
2
* This file is part of the Aaru Data Preservation Suite.
3
* Copyright (c) 2019-2026 Natalia Portillo.
4
*
5
* This library is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU Lesser General Public License as
7
* published by the Free Software Foundation; either version 2.1 of the
8
* License, or (at your option) any later version.
9
*
10
* This library is distributed in the hope that it will be useful, but
11
* WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
14
*
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include <stdint.h>
20
#include <stdio.h>
21
#include <stdlib.h>
22
23
#include "
aaruformat.h
"
24
#include "
internal.h
"
25
#include "
log.h
"
26
#include "utarray.h"
27
80
UT_array *
process_index_v1
(
aaruformat_context
*ctx)
81
{
82
TRACE
(
"Entering process_index_v1(%p)"
, ctx);
83
84
UT_array *index_entries = NULL;
85
IndexEntry
entry;
86
87
if
(ctx == NULL || ctx->
imageStream
== NULL)
return
NULL;
88
89
// Initialize the index entries array
90
const
UT_icd index_entry_icd = {
sizeof
(
IndexEntry
), NULL, NULL, NULL};
91
92
utarray_new(index_entries, &index_entry_icd);
93
94
if
(index_entries == NULL)
95
{
96
FATAL
(
"Could not allocate memory for index entries array."
);
97
TRACE
(
"Exiting process_index_v1() = NULL"
);
98
return
NULL;
99
}
100
101
// Read the index header
102
TRACE
(
"Reading index header at position %llu"
, ctx->
header
.
indexOffset
);
103
if
(
aaruf_fseek
(ctx->
imageStream
, (
aaru_off_t
)ctx->
header
.
indexOffset
, SEEK_SET) != 0)
104
{
105
FATAL
(
"Could not seek to index header at %llu."
, ctx->
header
.
indexOffset
);
106
utarray_free(index_entries);
107
108
TRACE
(
"Exiting process_index_v1() = NULL"
);
109
return
NULL;
110
}
111
112
IndexHeader
idx_header;
113
if
(fread(&idx_header,
sizeof
(
IndexHeader
), 1, ctx->
imageStream
) != 1)
114
{
115
FATAL
(
"Could not read index header at %llu."
, ctx->
header
.
indexOffset
);
116
utarray_free(index_entries);
117
118
TRACE
(
"Exiting process_index_v1() = NULL"
);
119
return
NULL;
120
}
121
122
// Check if the index header is valid
123
if
(idx_header.
identifier
!=
IndexBlock
)
124
{
125
FATAL
(
"Incorrect index identifier."
);
126
utarray_free(index_entries);
127
128
TRACE
(
"Exiting process_index_v1() = NULL"
);
129
return
NULL;
130
}
131
132
for
(
int
i = 0; i < idx_header.
entries
; i++)
133
{
134
if
(fread(&entry,
sizeof
(
IndexEntry
), 1, ctx->
imageStream
) != 1)
135
{
136
FATAL
(
"Could not read index entry %d at %llu."
, i, ctx->
header
.
indexOffset
);
137
utarray_free(index_entries);
138
139
TRACE
(
"Exiting process_index_v1() = NULL"
);
140
return
NULL;
141
}
142
143
utarray_push_back(index_entries, &entry);
144
}
145
146
TRACE
(
"Read %d index entries from index block at position %llu"
, idx_header.
entries
, ctx->
header
.
indexOffset
);
147
return
index_entries;
148
}
149
226
int32_t
verify_index_v1
(
aaruformat_context
*ctx)
227
{
228
TRACE
(
"Entering verify_index_v1(%p)"
, ctx);
229
230
size_t
read_bytes = 0;
231
IndexHeader
index_header;
232
uint64_t crc64 = 0;
233
IndexEntry
*index_entries = NULL;
234
235
if
(ctx == NULL || ctx->
imageStream
== NULL)
236
{
237
FATAL
(
"Invalid context or image stream."
);
238
239
TRACE
(
"Exiting verify_index_v1() = AARUF_ERROR_NOT_AARUFORMAT"
);
240
return
AARUF_ERROR_NOT_AARUFORMAT
;
241
}
242
243
// This will traverse all blocks and check their CRC64 without uncompressing them
244
TRACE
(
"Checking index integrity at %llu."
, ctx->
header
.
indexOffset
);
245
if
(
aaruf_fseek
(ctx->
imageStream
, (
aaru_off_t
)ctx->
header
.
indexOffset
, SEEK_SET) != 0)
246
{
247
FATAL
(
"Could not seek to index header at %llu."
, ctx->
header
.
indexOffset
);
248
249
TRACE
(
"Exiting verify_index_v1() = AARUF_ERROR_CANNOT_READ_HEADER"
);
250
return
AARUF_ERROR_CANNOT_READ_HEADER
;
251
}
252
253
// Read the index header
254
TRACE
(
"Reading index header at position %llu"
, ctx->
header
.
indexOffset
);
255
read_bytes = fread(&index_header, 1,
sizeof
(
IndexHeader
), ctx->
imageStream
);
256
257
if
(read_bytes !=
sizeof
(
IndexHeader
))
258
{
259
FATAL
(
"Could not read index header."
);
260
261
TRACE
(
"Exiting verify_index_v1() = AARUF_ERROR_CANNOT_READ_HEADER"
);
262
return
AARUF_ERROR_CANNOT_READ_HEADER
;
263
}
264
265
if
(index_header.
identifier
!=
IndexBlock
)
266
{
267
FATAL
(
"Incorrect index identifier."
);
268
269
TRACE
(
"Exiting verify_index_v1() = AARUF_ERROR_CANNOT_READ_INDEX"
);
270
return
AARUF_ERROR_CANNOT_READ_INDEX
;
271
}
272
273
TRACE
(
"Index at %llu contains %d entries."
, ctx->
header
.
indexOffset
, index_header.
entries
);
274
fprintf(stderr,
"Index at %llu contains %d entries."
, ctx->
header
.
indexOffset
, index_header.
entries
);
275
276
index_entries = malloc(
sizeof
(
IndexEntry
) * index_header.
entries
);
277
278
if
(index_entries == NULL)
279
{
280
FATAL
(
"Cannot allocate memory for index entries."
);
281
return
AARUF_ERROR_NOT_ENOUGH_MEMORY
;
282
}
283
284
read_bytes = fread(index_entries, 1,
sizeof
(
IndexEntry
) * index_header.
entries
, ctx->
imageStream
);
285
286
if
(read_bytes !=
sizeof
(
IndexEntry
) * index_header.
entries
)
287
{
288
FATAL
(
"Could not read index entries."
);
289
free(index_entries);
290
291
TRACE
(
"Exiting verify_index_v1() = AARUF_ERROR_CANNOT_READ_INDEX"
);
292
return
AARUF_ERROR_CANNOT_READ_INDEX
;
293
}
294
295
crc64 =
aaruf_crc64_data
((
const
uint8_t *)index_entries,
sizeof
(
IndexEntry
) * index_header.
entries
);
296
297
// Due to how C# wrote it, it is effectively reversed
298
if
(ctx->
header
.
imageMajorVersion
<=
AARUF_VERSION_V1
) crc64 =
bswap_64
(crc64);
299
300
if
(crc64 != index_header.
crc64
)
301
{
302
FATAL
(
"Expected index CRC 0x%16llX but got 0x%16llX."
, index_header.
crc64
, crc64);
303
free(index_entries);
304
305
TRACE
(
"Exiting verify_index_v1() = AARUF_ERROR_INVALID_BLOCK_CRC"
);
306
return
AARUF_ERROR_INVALID_BLOCK_CRC
;
307
}
308
309
free(index_entries);
310
311
TRACE
(
"Exiting verify_index_v1() = AARUF_OK"
);
312
return
AARUF_STATUS_OK
;
313
}
aaruformat.h
AARUF_VERSION_V1
#define AARUF_VERSION_V1
First on‑disk version (C# implementation).
Definition
consts.h:71
aaruf_crc64_data
uint64_t aaruf_crc64_data(const uint8_t *data, uint32_t len)
Definition
crc64.c:160
bswap_64
#define bswap_64(x)
Definition
endian.h:81
IndexBlock
@ IndexBlock
Block containing the index (v1).
Definition
enums.h:169
AARUF_STATUS_OK
#define AARUF_STATUS_OK
Sector present and read without uncorrectable errors.
Definition
errors.h:82
AARUF_ERROR_CANNOT_READ_HEADER
#define AARUF_ERROR_CANNOT_READ_HEADER
Failed to read container header.
Definition
errors.h:45
AARUF_ERROR_NOT_ENOUGH_MEMORY
#define AARUF_ERROR_NOT_ENOUGH_MEMORY
Memory allocation failure (critical).
Definition
errors.h:48
AARUF_ERROR_INVALID_BLOCK_CRC
#define AARUF_ERROR_INVALID_BLOCK_CRC
CRC64 mismatch indicating corruption.
Definition
errors.h:57
AARUF_ERROR_CANNOT_READ_INDEX
#define AARUF_ERROR_CANNOT_READ_INDEX
Index block unreadable / truncated / bad identifier.
Definition
errors.h:43
AARUF_ERROR_NOT_AARUFORMAT
#define AARUF_ERROR_NOT_AARUFORMAT
Input file/stream failed magic or structural validation.
Definition
errors.h:40
internal.h
process_index_v1
UT_array * process_index_v1(aaruformat_context *ctx)
Processes an index block (version 1) from the image stream.
Definition
index_v1.c:80
aaruf_fseek
static int aaruf_fseek(FILE *stream, aaru_off_t offset, int origin)
Definition
internal.h:46
verify_index_v1
int32_t verify_index_v1(aaruformat_context *ctx)
Verifies the integrity of an index block (version 1) in the image stream.
Definition
index_v1.c:226
aaru_off_t
int64_t aaru_off_t
Definition
internal.h:42
log.h
FATAL
#define FATAL(fmt,...)
Definition
log.h:40
TRACE
#define TRACE(fmt,...)
Definition
log.h:25
AaruHeaderV2::indexOffset
uint64_t indexOffset
Absolute byte offset to primary index block (MUST be > 0; 0 => corrupt/unreadable).
Definition
header.h:115
AaruHeaderV2::imageMajorVersion
uint8_t imageMajorVersion
Container format major version.
Definition
header.h:110
IndexEntry
Single index entry describing a block's type, (optional) data classification, and file offset.
Definition
index.h:109
IndexHeader
Index header (version 1) for legacy images (identifier == IndexBlock).
Definition
index.h:67
IndexHeader::crc64
uint64_t crc64
CRC64-ECMA of the entries array (legacy byte-swapped for early images).
Definition
index.h:70
IndexHeader::identifier
uint32_t identifier
Block identifier (must be BlockType::IndexBlock).
Definition
index.h:68
IndexHeader::entries
uint16_t entries
Number of IndexEntry records that follow immediately.
Definition
index.h:69
aaruformat_context
Master context representing an open or in‑creation Aaru image.
Definition
context.h:178
aaruformat_context::header
AaruHeaderV2 header
Parsed container header (v2).
Definition
context.h:181
aaruformat_context::imageStream
FILE * imageStream
Underlying FILE* stream (binary mode).
Definition
context.h:182
src
index
index_v1.c
Generated by
1.18.0