Coverage Report

Created: 2025-06-24 07:14

/src/libpff/libpff/libpff_descriptors_index.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Descriptors index functions
3
 *
4
 * Copyright (C) 2008-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <types.h>
25
26
#include "libpff_definitions.h"
27
#include "libpff_descriptors_index.h"
28
#include "libpff_index.h"
29
#include "libpff_index_value.h"
30
#include "libpff_index_values_list.h"
31
#include "libpff_io_handle.h"
32
#include "libpff_libbfio.h"
33
#include "libpff_libcdata.h"
34
#include "libpff_libcerror.h"
35
36
/* Creates a descriptors index
37
 * Make sure the value descriptors_index is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libpff_descriptors_index_initialize(
41
     libpff_descriptors_index_t **descriptors_index,
42
     off64_t root_node_offset,
43
     uint64_t root_node_back_pointer,
44
     libcerror_error_t **error )
45
8.85k
{
46
8.85k
  static char *function = "libpff_descriptors_index_initialize";
47
48
8.85k
  if( descriptors_index == NULL )
49
0
  {
50
0
    libcerror_error_set(
51
0
     error,
52
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
53
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
54
0
     "%s: invalid descriptors index.",
55
0
     function );
56
57
0
    return( -1 );
58
0
  }
59
8.85k
  if( *descriptors_index != NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
64
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
65
0
     "%s: invalid descriptors index value already set.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
8.85k
  *descriptors_index = memory_allocate_structure(
71
8.85k
                        libpff_descriptors_index_t );
72
73
8.85k
  if( *descriptors_index == NULL )
74
0
  {
75
0
    libcerror_error_set(
76
0
     error,
77
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
78
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
79
0
     "%s: unable to create descriptors index.",
80
0
     function );
81
82
0
    goto on_error;
83
0
  }
84
8.85k
  if( memory_set(
85
8.85k
       *descriptors_index,
86
8.85k
       0,
87
8.85k
       sizeof( libpff_descriptors_index_t ) ) == NULL )
88
0
  {
89
0
    libcerror_error_set(
90
0
     error,
91
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
92
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
93
0
     "%s: unable to clear descriptors index.",
94
0
     function );
95
96
0
    memory_free(
97
0
     *descriptors_index );
98
99
0
    *descriptors_index = NULL;
100
101
0
    return( -1 );
102
0
  }
103
8.85k
  if( libpff_index_initialize(
104
8.85k
       &( ( *descriptors_index )->index ),
105
8.85k
       LIBPFF_INDEX_TYPE_DESCRIPTOR,
106
8.85k
       root_node_offset,
107
8.85k
       root_node_back_pointer,
108
8.85k
       error ) != 1 )
109
0
  {
110
0
    libcerror_error_set(
111
0
     error,
112
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
113
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
114
0
     "%s: unable to create index.",
115
0
     function );
116
117
0
    goto on_error;
118
0
  }
119
8.85k
  if( libcdata_btree_initialize(
120
8.85k
       &( ( *descriptors_index )->recovered_index_values_tree ),
121
8.85k
       257,
122
8.85k
       error ) != 1 )
123
0
  {
124
0
    libcerror_error_set(
125
0
     error,
126
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
127
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
128
0
     "%s: unable to create recovered index values B-tree.",
129
0
     function );
130
131
0
    goto on_error;
132
0
  }
133
8.85k
  return( 1 );
134
135
0
on_error:
136
0
  if( *descriptors_index != NULL )
137
0
  {
138
0
    if( ( *descriptors_index )->recovered_index_values_tree != NULL )
139
0
    {
140
0
      libcdata_btree_free(
141
0
       &( ( *descriptors_index )->recovered_index_values_tree ),
142
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libpff_index_values_list_free,
143
0
       NULL );
144
0
    }
145
0
    if( ( *descriptors_index )->index != NULL )
146
0
    {
147
0
      libpff_index_free(
148
0
       &( ( *descriptors_index )->index ),
149
0
       NULL );
150
0
    }
151
0
    memory_free(
152
0
     *descriptors_index );
153
154
0
    *descriptors_index = NULL;
155
0
  }
156
0
  return( -1 );
157
8.85k
}
158
159
/* Frees a descriptors index
160
 * Returns 1 if successful or -1 on error
161
 */
162
int libpff_descriptors_index_free(
163
     libpff_descriptors_index_t **descriptors_index,
164
     libcerror_error_t **error )
165
8.85k
{
166
8.85k
  static char *function = "libpff_descriptors_index_free";
167
8.85k
  int result            = 1;
168
169
8.85k
  if( descriptors_index == NULL )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
174
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
175
0
     "%s: invalid descriptors index.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
8.85k
  if( *descriptors_index != NULL )
181
8.85k
  {
182
8.85k
    if( libcdata_btree_free(
183
8.85k
         &( ( *descriptors_index )->recovered_index_values_tree ),
184
8.85k
         (int (*)(intptr_t **, libcerror_error_t **)) &libpff_index_values_list_free,
185
8.85k
         error ) != 1 )
186
0
    {
187
0
      libcerror_error_set(
188
0
       error,
189
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
190
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
191
0
       "%s: unable to free recovered index values tree.",
192
0
       function );
193
194
0
      result = -1;
195
0
    }
196
8.85k
    if( libpff_index_free(
197
8.85k
         &( ( *descriptors_index )->index ),
198
8.85k
         error ) != 1 )
199
0
    {
200
0
      libcerror_error_set(
201
0
       error,
202
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
203
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
204
0
       "%s: unable to free index.",
205
0
       function );
206
207
0
      result = -1;
208
0
    }
209
8.85k
    memory_free(
210
8.85k
     *descriptors_index );
211
212
8.85k
    *descriptors_index = NULL;
213
8.85k
  }
214
8.85k
  return( result );
215
8.85k
}
216
217
/* Retrieves an index value for a specific identifier
218
 * Returns 1 if successful, 0 if no index value was found or -1 on error
219
 */
220
int libpff_descriptors_index_get_index_value_by_identifier(
221
     libpff_descriptors_index_t *descriptors_index,
222
     libpff_io_handle_t *io_handle,
223
     libbfio_handle_t *file_io_handle,
224
     uint32_t descriptor_identifier,
225
     uint8_t recovered,
226
     libpff_index_value_t **index_value,
227
     libcerror_error_t **error )
228
7.67k
{
229
7.67k
  libcdata_tree_node_t *upper_node              = NULL;
230
7.67k
  libpff_index_value_t *lookup_index_value      = NULL;
231
7.67k
  libpff_index_value_t *safe_index_value        = NULL;
232
7.67k
  libpff_index_values_list_t *index_values_list = NULL;
233
7.67k
  static char *function                         = "libpff_descriptors_index_get_index_value_by_identifier";
234
7.67k
  int result                                    = 0;
235
236
7.67k
  if( descriptors_index == NULL )
237
0
  {
238
0
    libcerror_error_set(
239
0
     error,
240
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
241
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
242
0
     "%s: invalid descriptors index.",
243
0
     function );
244
245
0
    return( -1 );
246
0
  }
247
7.67k
  if( index_value == NULL )
248
0
  {
249
0
    libcerror_error_set(
250
0
     error,
251
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
252
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
253
0
     "%s: invalid index value.",
254
0
     function );
255
256
0
    return( -1 );
257
0
  }
258
7.67k
  if( recovered == 0 )
259
7.67k
  {
260
7.67k
    result = libpff_index_get_value_by_identifier(
261
7.67k
        descriptors_index->index,
262
7.67k
        io_handle,
263
7.67k
        file_io_handle,
264
7.67k
        descriptor_identifier,
265
7.67k
        index_value,
266
7.67k
        error );
267
268
7.67k
    if( result == -1 )
269
529
    {
270
529
      libcerror_error_set(
271
529
       error,
272
529
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
273
529
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
274
529
       "%s: unable to retrieve index value: %" PRIu32 " from index.",
275
529
       function,
276
529
       descriptor_identifier );
277
278
529
      goto on_error;
279
529
    }
280
7.67k
  }
281
0
  else
282
0
  {
283
0
    if( libpff_index_value_initialize(
284
0
         &lookup_index_value,
285
0
         error ) != 1 )
286
0
    {
287
0
      libcerror_error_set(
288
0
       error,
289
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
290
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
291
0
       "%s: unable to create lookup index value.",
292
0
       function );
293
294
0
      goto on_error;
295
0
    }
296
0
    lookup_index_value->identifier = descriptor_identifier;
297
298
0
    result = libcdata_btree_get_value_by_value(
299
0
              descriptors_index->recovered_index_values_tree,
300
0
              (intptr_t *) lookup_index_value,
301
0
              (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libpff_index_values_list_compare,
302
0
              &upper_node,
303
0
              (intptr_t **) &index_values_list,
304
0
              error );
305
306
0
    if( result == -1 )
307
0
    {
308
0
      libcerror_error_set(
309
0
       error,
310
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
311
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
312
0
       "%s: unable to retrieve recovered index value: %" PRIu32 " list from tree.",
313
0
       function,
314
0
       descriptor_identifier );
315
316
0
      goto on_error;
317
0
    }
318
0
    else if( result != 0 )
319
0
    {
320
0
      if( libpff_index_values_list_get_value_by_index(
321
0
           index_values_list,
322
0
           0,
323
0
           &safe_index_value,
324
0
           error ) != 1 )
325
0
      {
326
0
        libcerror_error_set(
327
0
         error,
328
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
329
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
330
0
         "%s: unable to retrieve retrieve recovered index value: %" PRIu32 " list entry: 0.",
331
0
         function,
332
0
         descriptor_identifier );
333
334
0
        goto on_error;
335
0
      }
336
0
      if( safe_index_value == NULL )
337
0
      {
338
0
        libcerror_error_set(
339
0
         error,
340
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
341
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
342
0
         "%s: missing recovered index value: %" PRIu32 " list entry: 0.",
343
0
         function,
344
0
         descriptor_identifier );
345
346
0
        goto on_error;
347
0
      }
348
0
      lookup_index_value->data_identifier              = lookup_index_value->data_identifier;
349
0
      lookup_index_value->local_descriptors_identifier = lookup_index_value->local_descriptors_identifier;
350
0
      lookup_index_value->parent_identifier            = lookup_index_value->parent_identifier;
351
352
0
      *index_value = lookup_index_value;
353
0
    }
354
0
  }
355
7.14k
  return( result );
356
357
529
on_error:
358
529
  if( lookup_index_value != NULL )
359
0
  {
360
0
    libpff_index_value_free(
361
0
     &lookup_index_value,
362
0
     NULL );
363
0
  }
364
529
  return( -1 );
365
7.67k
}
366
367
/* Inserts a recovered index value into the descriptors index
368
 * Returns 1 if successful or -1 on error
369
 */
370
int libpff_descriptors_index_insert_recovered_index_value(
371
     libpff_descriptors_index_t *descriptors_index,
372
     libpff_index_value_t *index_value,
373
     libcerror_error_t **error )
374
0
{
375
0
  libcdata_tree_node_t *upper_node                       = NULL;
376
0
  libpff_index_values_list_t *existing_index_values_list = NULL;
377
0
  libpff_index_values_list_t *index_values_list          = NULL;
378
0
  static char *function                                  = "libpff_descriptors_index_insert_recovered_index_value";
379
0
  int result                                             = 0;
380
0
  int value_index                                        = 0;
381
382
0
  if( descriptors_index == NULL )
383
0
  {
384
0
    libcerror_error_set(
385
0
     error,
386
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
387
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
388
0
     "%s: invalid descriptors index.",
389
0
     function );
390
391
0
    return( -1 );
392
0
  }
393
0
  if( index_value == NULL )
394
0
  {
395
0
    libcerror_error_set(
396
0
     error,
397
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
398
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
399
0
     "%s: invalid index value.",
400
0
     function );
401
402
0
    return( -1 );
403
0
  }
404
0
  if( libpff_index_values_list_initialize(
405
0
       &index_values_list,
406
0
       error ) != 1 )
407
0
  {
408
0
    libcerror_error_set(
409
0
     error,
410
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
411
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
412
0
     "%s: unable to create index values list.",
413
0
     function );
414
415
0
    goto on_error;
416
0
  }
417
0
  index_values_list->identifier = index_value->identifier;
418
419
0
  result = libcdata_btree_insert_value(
420
0
            descriptors_index->recovered_index_values_tree,
421
0
            &value_index,
422
0
            (intptr_t *) index_values_list,
423
0
            (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libpff_index_values_list_compare,
424
0
            &upper_node,
425
0
            (intptr_t **) &existing_index_values_list,
426
0
            error );
427
428
0
  if( result == -1 )
429
0
  {
430
0
    libcerror_error_set(
431
0
     error,
432
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
433
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
434
0
     "%s: unable to insert recovered descriptors index value: %" PRIu64 " list.",
435
0
     function,
436
0
     index_value->identifier );
437
438
0
    goto on_error;
439
0
  }
440
0
  else if( result != 0 )
441
0
  {
442
0
    existing_index_values_list = index_values_list;
443
0
    index_values_list          = NULL;
444
0
  }
445
0
  else
446
0
  {
447
0
    if( libpff_index_values_list_free(
448
0
         &index_values_list,
449
0
         error ) != 1 )
450
0
    {
451
0
      libcerror_error_set(
452
0
       error,
453
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
454
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
455
0
       "%s: unable to free index values list.",
456
0
       function );
457
458
0
      goto on_error;
459
0
    }
460
0
  }
461
0
  if( libpff_index_values_list_append_value(
462
0
       existing_index_values_list,
463
0
       index_value,
464
0
       error ) != 1 )
465
0
  {
466
0
    libcerror_error_set(
467
0
     error,
468
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
469
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
470
0
     "%s: unable to append index value to list.",
471
0
     function );
472
473
0
    goto on_error;
474
0
  }
475
0
  return( 1 );
476
477
0
on_error:
478
0
  if( index_values_list != NULL )
479
0
  {
480
0
    libpff_index_values_list_free(
481
0
     &index_values_list,
482
0
     NULL );
483
0
  }
484
0
  return( -1 );
485
0
}
486