Coverage Report

Created: 2025-06-13 07:22

/src/libpff/libpff/libpff_local_descriptors.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Local descriptors 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 <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libpff_definitions.h"
28
#include "libpff_io_handle.h"
29
#include "libpff_libbfio.h"
30
#include "libpff_libcerror.h"
31
#include "libpff_libcnotify.h"
32
#include "libpff_libfcache.h"
33
#include "libpff_libfdata.h"
34
#include "libpff_local_descriptors_node.h"
35
#include "libpff_local_descriptor_value.h"
36
#include "libpff_local_descriptors.h"
37
#include "libpff_offsets_index.h"
38
#include "libpff_unused.h"
39
40
#include "pff_local_descriptors_node.h"
41
42
/* Creates local descriptors
43
 * Make sure the value local_descriptors is referencing, is set to NULL
44
 * Returns 1 if successful or -1 on error
45
 */
46
int libpff_local_descriptors_initialize(
47
     libpff_local_descriptors_t **local_descriptors,
48
     libpff_io_handle_t *io_handle,
49
     libpff_offsets_index_t *offsets_index,
50
     uint32_t descriptor_identifier,
51
     uint64_t root_node_data_identifier,
52
     uint8_t recovered,
53
     libcerror_error_t **error )
54
5.83k
{
55
5.83k
  static char *function = "libpff_local_descriptors_initialize";
56
57
5.83k
  if( local_descriptors == NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
63
0
     "%s: invalid local descriptors.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
5.83k
  if( *local_descriptors != NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
73
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
74
0
     "%s: invalid local descriptors value already set.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
5.83k
  if( io_handle == NULL )
80
0
  {
81
0
    libcerror_error_set(
82
0
     error,
83
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
84
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
85
0
     "%s: invalid IO handle.",
86
0
     function );
87
88
0
    return( -1 );
89
0
  }
90
5.83k
  if( offsets_index == NULL )
91
0
  {
92
0
    libcerror_error_set(
93
0
     error,
94
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
95
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
96
0
     "%s: invalid offsets index.",
97
0
     function );
98
99
0
    return( -1 );
100
0
  }
101
5.83k
  *local_descriptors = memory_allocate_structure(
102
5.83k
                        libpff_local_descriptors_t );
103
104
5.83k
  if( *local_descriptors == NULL )
105
0
  {
106
0
    libcerror_error_set(
107
0
     error,
108
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
109
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
110
0
     "%s: unable to create local descriptors.",
111
0
     function );
112
113
0
    goto on_error;
114
0
  }
115
5.83k
  if( memory_set(
116
5.83k
       *local_descriptors,
117
5.83k
       0,
118
5.83k
       sizeof( libpff_local_descriptors_t ) ) == NULL )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
123
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
124
0
     "%s: unable to clear local descriptors.",
125
0
     function );
126
127
0
    memory_free(
128
0
     *local_descriptors );
129
130
0
    *local_descriptors = NULL;
131
132
0
    return( -1 );
133
0
  }
134
5.83k
  if( libfcache_cache_initialize(
135
5.83k
       &( ( *local_descriptors )->local_descriptors_nodes_cache ),
136
5.83k
       LIBPFF_MAXIMUM_CACHE_ENTRIES_LOCAL_DESCRIPTORS_NODES,
137
5.83k
       error ) != 1 )
138
0
  {
139
0
    libcerror_error_set(
140
0
     error,
141
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
142
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
143
0
     "%s: unable to create local descriptors nodes cache.",
144
0
     function );
145
146
0
    goto on_error;
147
0
  }
148
5.83k
  ( *local_descriptors )->io_handle                 = io_handle;
149
5.83k
  ( *local_descriptors )->offsets_index             = offsets_index;
150
5.83k
  ( *local_descriptors )->descriptor_identifier     = descriptor_identifier;
151
5.83k
  ( *local_descriptors )->root_node_data_identifier = root_node_data_identifier;
152
5.83k
  ( *local_descriptors )->recovered                 = recovered;
153
154
5.83k
  return( 1 );
155
156
0
on_error:
157
0
  if( *local_descriptors != NULL )
158
0
  {
159
0
    memory_free(
160
0
     *local_descriptors );
161
162
0
    *local_descriptors = NULL;
163
0
  }
164
0
  return( -1 );
165
5.83k
}
166
167
/* Frees local descriptors
168
 * Returns 1 if successful or -1 on error
169
 */
170
int libpff_local_descriptors_free(
171
     libpff_local_descriptors_t **local_descriptors,
172
     libcerror_error_t **error )
173
5.83k
{
174
5.83k
  static char *function = "libpff_local_descriptors_free";
175
5.83k
  int result            = 1;
176
177
5.83k
  if( local_descriptors == NULL )
178
0
  {
179
0
    libcerror_error_set(
180
0
     error,
181
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
182
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
183
0
     "%s: invalid local descriptors.",
184
0
     function );
185
186
0
    return( -1 );
187
0
  }
188
5.83k
  if( *local_descriptors != NULL )
189
5.83k
  {
190
5.83k
    if( libfcache_cache_free(
191
5.83k
         &( ( *local_descriptors )->local_descriptors_nodes_cache ),
192
5.83k
         error ) != 1 )
193
0
    {
194
0
      libcerror_error_set(
195
0
       error,
196
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
197
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
198
0
       "%s: unable to free local descriptors nodes cache.",
199
0
       function );
200
201
0
      result = -1;
202
0
    }
203
5.83k
    memory_free(
204
5.83k
     *local_descriptors );
205
206
5.83k
    *local_descriptors = NULL;
207
5.83k
  }
208
5.83k
  return( result );
209
5.83k
}
210
211
/* Clones the local descriptors
212
 * Returns 1 if successful or -1 on error
213
 */
214
int libpff_local_descriptors_clone(
215
     libpff_local_descriptors_t **destination_local_descriptors,
216
     libpff_local_descriptors_t *source_local_descriptors,
217
     libcerror_error_t **error )
218
0
{
219
0
  static char *function = "libpff_local_descriptors_clone";
220
221
0
  if( destination_local_descriptors == NULL )
222
0
  {
223
0
    libcerror_error_set(
224
0
     error,
225
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
226
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
227
0
     "%s: invalid destination local descriptors.",
228
0
     function );
229
230
0
    return( -1 );
231
0
  }
232
0
  if( *destination_local_descriptors != NULL )
233
0
  {
234
0
    libcerror_error_set(
235
0
     error,
236
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
237
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
238
0
     "%s: invalid destination local descriptors already set.",
239
0
     function );
240
241
0
    return( -1 );
242
0
  }
243
0
  if( source_local_descriptors == NULL )
244
0
  {
245
0
    *destination_local_descriptors = NULL;
246
247
0
    return( 1 );
248
0
  }
249
0
  if( libpff_local_descriptors_initialize(
250
0
       destination_local_descriptors,
251
0
       source_local_descriptors->io_handle,
252
0
       source_local_descriptors->offsets_index,
253
0
       source_local_descriptors->descriptor_identifier,
254
0
       source_local_descriptors->root_node_data_identifier,
255
0
       source_local_descriptors->recovered,
256
0
       error ) != 1 )
257
0
  {
258
0
    libcerror_error_set(
259
0
     error,
260
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
261
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
262
0
     "%s: unable to create destination local descriptors.",
263
0
     function );
264
265
0
    return( -1 );
266
0
  }
267
0
  return( 1 );
268
0
}
269
270
/* Retrieves the leaf node from an local descriptors node for the specific identifier
271
 * Returns 1 if successful, 0 if no leaf node was found or -1 on error
272
 */
273
int libpff_local_descriptors_get_leaf_node_from_node_by_identifier(
274
     libpff_local_descriptors_t *local_descriptors,
275
     libpff_io_handle_t *io_handle,
276
     libbfio_handle_t *file_io_handle,
277
     uint64_t identifier,
278
     uint64_t data_identifier,
279
     libpff_local_descriptors_node_t **leaf_node,
280
     uint16_t *leaf_node_entry_index,
281
     libcerror_error_t **error )
282
13.6k
{
283
13.6k
  libpff_index_value_t *offsets_index_value               = NULL;
284
13.6k
  libpff_local_descriptors_node_t *local_descriptors_node = NULL;
285
13.6k
  uint8_t *node_entry_data                                = NULL;
286
13.6k
  static char *function                                   = "libpff_local_descriptors_get_leaf_node_from_node_by_identifier";
287
13.6k
  uint64_t entry_identifier                               = 0;
288
13.6k
  uint64_t sub_node_identifier                            = 0;
289
13.6k
  uint16_t entry_index                                    = 0;
290
13.6k
  int result                                              = 0;
291
292
13.6k
  if( local_descriptors == NULL )
293
0
  {
294
0
    libcerror_error_set(
295
0
     error,
296
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
297
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
298
0
     "%s: invalid local descriptors.",
299
0
     function );
300
301
0
    return( -1 );
302
0
  }
303
13.6k
  if( io_handle == NULL )
304
0
  {
305
0
    libcerror_error_set(
306
0
     error,
307
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
308
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
309
0
     "%s: invalid IO handle.",
310
0
     function );
311
312
0
    return( -1 );
313
0
  }
314
13.6k
  if( leaf_node == NULL )
315
0
  {
316
0
    libcerror_error_set(
317
0
     error,
318
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
319
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
320
0
     "%s: invalid leaf node.",
321
0
     function );
322
323
0
    return( -1 );
324
0
  }
325
13.6k
  if( leaf_node_entry_index == NULL )
326
0
  {
327
0
    libcerror_error_set(
328
0
     error,
329
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
330
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
331
0
     "%s: invalid leaf node entry index.",
332
0
     function );
333
334
0
    return( -1 );
335
0
  }
336
#if defined( HAVE_DEBUG_OUTPUT )
337
  if( libcnotify_verbose != 0 )
338
  {
339
    libcnotify_printf(
340
     "%s: requested identifier\t: 0x%08" PRIx64 " (%" PRIu64 ").\n",
341
     function,
342
     data_identifier,
343
     data_identifier );
344
  }
345
#endif
346
/* TODO handle multiple recovered offsets index values */
347
13.6k
  result = libpff_offsets_index_get_index_value_by_identifier(
348
13.6k
            local_descriptors->offsets_index,
349
13.6k
            io_handle,
350
13.6k
            file_io_handle,
351
13.6k
            data_identifier,
352
13.6k
            local_descriptors->recovered,
353
13.6k
            0,
354
13.6k
            &offsets_index_value,
355
13.6k
            error );
356
357
13.6k
  if( result == -1 )
358
7
  {
359
7
    libcerror_error_set(
360
7
     error,
361
7
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
362
7
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
363
7
     "%s: unable to find offsets index value: 0x%08" PRIx64 " (%" PRIu64 ").",
364
7
     function,
365
7
     data_identifier,
366
7
     data_identifier );
367
368
7
    goto on_error;
369
7
  }
370
13.6k
  else if( result == 0 )
371
3.32k
  {
372
3.32k
    return( 0 );
373
3.32k
  }
374
10.2k
  if( offsets_index_value == NULL )
375
0
  {
376
0
    libcerror_error_set(
377
0
     error,
378
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
379
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
380
0
     "%s: missing offsets index value: 0x%08" PRIx64 " (%" PRIu64 ").",
381
0
     function,
382
0
     data_identifier,
383
0
     data_identifier );
384
385
0
    goto on_error;
386
0
  }
387
#if defined( HAVE_DEBUG_OUTPUT )
388
  if( libcnotify_verbose != 0 )
389
  {
390
    libcnotify_printf(
391
     "%s: local descriptors node: identifier: %" PRIu64 " (%s) at offset: 0x%08" PRIx64 " of size: %" PRIu32 "\n",
392
     function,
393
     offsets_index_value->identifier,
394
     ( ( offsets_index_value->identifier & LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL ) ? "internal" : "external" ),
395
     offsets_index_value->file_offset,
396
     offsets_index_value->data_size );
397
  }
398
#endif
399
10.2k
  if( libpff_local_descriptors_node_initialize(
400
10.2k
       &local_descriptors_node,
401
10.2k
       error ) != 1 )
402
0
  {
403
0
    libcerror_error_set(
404
0
     error,
405
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
406
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
407
0
     "%s: unable to create local descriptors node.",
408
0
     function );
409
410
0
    goto on_error;
411
0
  }
412
10.2k
  if( libpff_local_descriptors_node_read_file_io_handle(
413
10.2k
       local_descriptors_node,
414
10.2k
       io_handle,
415
10.2k
       file_io_handle,
416
10.2k
       local_descriptors->descriptor_identifier,
417
10.2k
       data_identifier,
418
10.2k
       offsets_index_value->file_offset,
419
10.2k
       offsets_index_value->data_size,
420
10.2k
       error ) != 1 )
421
299
  {
422
299
    libcerror_error_set(
423
299
     error,
424
299
     LIBCERROR_ERROR_DOMAIN_IO,
425
299
     LIBCERROR_IO_ERROR_READ_FAILED,
426
299
     "%s: unable to read local descriptors node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
427
299
     function,
428
299
     offsets_index_value->file_offset,
429
299
     offsets_index_value->file_offset );
430
431
299
    goto on_error;
432
299
  }
433
9.98k
  for( entry_index = 0;
434
11.3k
       entry_index < local_descriptors_node->number_of_entries;
435
9.98k
       entry_index++ )
436
11.2k
  {
437
11.2k
    if( libpff_local_descriptors_node_get_entry_data(
438
11.2k
         local_descriptors_node,
439
11.2k
         entry_index,
440
11.2k
         &node_entry_data,
441
11.2k
         error ) != 1 )
442
0
    {
443
0
      libcerror_error_set(
444
0
       error,
445
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
446
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
447
0
       "%s: unable to retrieve node entry: %" PRIu16 " data.",
448
0
       function,
449
0
       entry_index );
450
451
0
      goto on_error;
452
0
    }
453
11.2k
    if( node_entry_data == NULL )
454
0
    {
455
0
      libcerror_error_set(
456
0
       error,
457
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
458
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
459
0
       "%s: missing node entry: %" PRIu16 " data.",
460
0
       function,
461
0
       entry_index );
462
463
0
      goto on_error;
464
0
    }
465
11.2k
    if( local_descriptors->io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
466
236
    {
467
236
      byte_stream_copy_to_uint32_little_endian(
468
236
       ( (pff_local_descriptor_branch_node_entry_type_32bit_t *) node_entry_data )->identifier,
469
236
       entry_identifier );
470
236
    }
471
11.0k
    else if( ( local_descriptors->io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
472
11.0k
          || ( local_descriptors->io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
473
11.0k
    {
474
11.0k
      byte_stream_copy_to_uint64_little_endian(
475
11.0k
       ( (pff_local_descriptor_branch_node_entry_type_64bit_t *) node_entry_data )->identifier,
476
11.0k
       entry_identifier );
477
11.0k
    }
478
    /* Ignore the upper 32-bit of local descriptor identifiers
479
     */
480
11.2k
    entry_identifier &= 0xffffffffUL;
481
482
11.2k
    if( local_descriptors_node->level != LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
483
236
    {
484
236
      if( ( entry_index == 0 )
485
236
       || ( identifier >= entry_identifier ) )
486
191
      {
487
191
        if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
488
191
        {
489
191
          byte_stream_copy_to_uint32_little_endian(
490
191
           ( (pff_local_descriptor_branch_node_entry_type_32bit_t *) node_entry_data )->sub_node_identifier,
491
191
           sub_node_identifier );
492
191
        }
493
0
        else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
494
0
              || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
495
0
        {
496
0
          byte_stream_copy_to_uint64_little_endian(
497
0
           ( (pff_local_descriptor_branch_node_entry_type_64bit_t *) node_entry_data )->sub_node_identifier,
498
0
           sub_node_identifier );
499
0
        }
500
191
      }
501
236
    }
502
11.0k
    else if( identifier == entry_identifier )
503
9.57k
    {
504
9.57k
      *leaf_node             = local_descriptors_node;
505
9.57k
      *leaf_node_entry_index = entry_index;
506
507
9.57k
      result = 1;
508
9.57k
    }
509
    /* A branch node contains the identifier of its first sub node
510
     */
511
11.2k
    if( identifier <= entry_identifier )
512
9.84k
    {
513
9.84k
      break;
514
9.84k
    }
515
11.2k
  }
516
9.98k
  if( local_descriptors_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
517
97
  {
518
97
    result = libpff_local_descriptors_get_leaf_node_from_node_by_identifier(
519
97
        local_descriptors,
520
97
              io_handle,
521
97
        file_io_handle,
522
97
        identifier,
523
97
        sub_node_identifier,
524
97
        leaf_node,
525
97
        leaf_node_entry_index,
526
97
        error );
527
528
97
    if( result == -1 )
529
10
    {
530
10
      libcerror_error_set(
531
10
       error,
532
10
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
533
10
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
534
10
       "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
535
10
       function,
536
10
       identifier,
537
10
       identifier,
538
10
       offsets_index_value->file_offset,
539
10
       offsets_index_value->file_offset );
540
541
10
      goto on_error;
542
10
    }
543
97
  }
544
9.97k
  if( ( local_descriptors_node != NULL )
545
9.97k
   && ( local_descriptors_node != *leaf_node ) )
546
396
  {
547
396
    if( libpff_local_descriptors_node_free(
548
396
         &local_descriptors_node,
549
396
         error ) != 1 )
550
0
    {
551
0
      libcerror_error_set(
552
0
       error,
553
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
554
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
555
0
       "%s: unable to free local descriptors node.",
556
0
       function );
557
558
0
      goto on_error;
559
0
    }
560
396
  }
561
9.97k
  if( libpff_index_value_free(
562
9.97k
       &offsets_index_value,
563
9.97k
       error ) != 1 )
564
0
  {
565
0
    libcerror_error_set(
566
0
     error,
567
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
568
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
569
0
     "%s: unable to free offsets index value.",
570
0
     function );
571
572
0
    goto on_error;
573
0
  }
574
9.97k
  return( result );
575
576
316
on_error:
577
316
  if( local_descriptors_node != NULL )
578
309
  {
579
309
    libpff_local_descriptors_node_free(
580
309
     &local_descriptors_node,
581
309
     NULL );
582
309
  }
583
316
  if( offsets_index_value != NULL )
584
309
  {
585
309
    libpff_index_value_free(
586
309
     &offsets_index_value,
587
309
     NULL );
588
309
  }
589
316
  return( -1 );
590
9.97k
}
591
592
/* Retrieves the value for the specific identifier
593
 * Returns 1 if successful, 0 if no value was found or -1 on error
594
 */
595
int libpff_local_descriptors_get_value_by_identifier(
596
     libpff_local_descriptors_t *local_descriptors,
597
     libpff_io_handle_t *io_handle,
598
     libbfio_handle_t *file_io_handle,
599
     uint64_t identifier,
600
     libpff_local_descriptor_value_t **local_descriptor_value,
601
     libcerror_error_t **error )
602
13.5k
{
603
13.5k
  libpff_local_descriptor_value_t *safe_local_descriptor_value = NULL;
604
13.5k
  libpff_local_descriptors_node_t *leaf_node                   = NULL;
605
13.5k
  uint8_t *node_entry_data                                     = NULL;
606
13.5k
  static char *function                                        = "libpff_local_descriptors_get_value_by_identifier";
607
13.5k
  uint16_t leaf_node_entry_index                               = 0;
608
13.5k
  int result                                                   = 0;
609
610
13.5k
  if( local_descriptors == NULL )
611
0
  {
612
0
    libcerror_error_set(
613
0
     error,
614
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
615
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
616
0
     "%s: invalid local descriptors.",
617
0
     function );
618
619
0
    return( -1 );
620
0
  }
621
13.5k
  if( local_descriptor_value == NULL )
622
0
  {
623
0
    libcerror_error_set(
624
0
     error,
625
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
626
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
627
0
     "%s: invalid local descriptor value.",
628
0
     function );
629
630
0
    return( -1 );
631
0
  }
632
#if defined( HAVE_DEBUG_OUTPUT )
633
  if( libcnotify_verbose != 0 )
634
  {
635
    libcnotify_printf(
636
     "%s: requested identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ").\n",
637
     function,
638
     identifier,
639
     identifier );
640
  }
641
#endif
642
13.5k
  result = libpff_local_descriptors_get_leaf_node_from_node_by_identifier(
643
13.5k
      local_descriptors,
644
13.5k
      io_handle,
645
13.5k
      file_io_handle,
646
13.5k
      identifier,
647
13.5k
      local_descriptors->root_node_data_identifier,
648
13.5k
      &leaf_node,
649
13.5k
      &leaf_node_entry_index,
650
13.5k
      error );
651
652
13.5k
  if( result == -1 )
653
306
  {
654
306
    libcerror_error_set(
655
306
     error,
656
306
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
657
306
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
658
306
     "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from root node.",
659
306
     function,
660
306
     identifier,
661
306
     identifier );
662
663
306
    goto on_error;
664
306
  }
665
13.2k
  else if( result != 0 )
666
9.88k
  {
667
9.88k
    if( libpff_local_descriptors_node_get_entry_data(
668
9.88k
         leaf_node,
669
9.88k
         leaf_node_entry_index,
670
9.88k
         &node_entry_data,
671
9.88k
         error ) != 1 )
672
309
    {
673
309
      libcerror_error_set(
674
309
       error,
675
309
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
676
309
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
677
309
       "%s: unable to retrieve node entry: %" PRIu16 " data.",
678
309
       function,
679
309
       leaf_node_entry_index );
680
681
309
      goto on_error;
682
309
    }
683
9.57k
    if( node_entry_data == NULL )
684
0
    {
685
0
      libcerror_error_set(
686
0
       error,
687
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
688
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
689
0
       "%s: missing node entry: %" PRIu16 " data.",
690
0
       function,
691
0
       leaf_node_entry_index );
692
693
0
      goto on_error;
694
0
    }
695
9.57k
    if( libpff_local_descriptor_value_initialize(
696
9.57k
         &safe_local_descriptor_value,
697
9.57k
         error ) != 1 )
698
0
    {
699
0
      libcerror_error_set(
700
0
       error,
701
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
702
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
703
0
       "%s: unable to create local descriptor value.",
704
0
       function );
705
706
0
      goto on_error;
707
0
    }
708
9.57k
    if( libpff_local_descriptor_value_read_data(
709
9.57k
         safe_local_descriptor_value,
710
9.57k
         io_handle,
711
9.57k
         node_entry_data,
712
9.57k
         (size_t) leaf_node->entry_size,
713
9.57k
         error ) != 1 )
714
0
    {
715
0
      libcerror_error_set(
716
0
       error,
717
0
       LIBCERROR_ERROR_DOMAIN_IO,
718
0
       LIBCERROR_IO_ERROR_READ_FAILED,
719
0
       "%s: unable to read local descriptor value.",
720
0
       function );
721
722
0
      goto on_error;
723
0
    }
724
9.57k
    if( libpff_local_descriptors_node_free(
725
9.57k
         &leaf_node,
726
9.57k
         error ) != 1 )
727
0
    {
728
0
      libcerror_error_set(
729
0
       error,
730
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
731
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
732
0
       "%s: unable to free leaf node.",
733
0
       function );
734
735
0
      goto on_error;
736
0
    }
737
9.57k
  }
738
12.9k
  *local_descriptor_value = safe_local_descriptor_value;
739
740
12.9k
  return( result );
741
742
615
on_error:
743
615
  if( safe_local_descriptor_value != NULL )
744
0
  {
745
0
    libpff_local_descriptor_value_free(
746
0
     &safe_local_descriptor_value,
747
0
     NULL );
748
0
  }
749
615
  if( leaf_node != NULL )
750
0
  {
751
0
    libpff_local_descriptors_node_free(
752
0
     &leaf_node,
753
0
     NULL );
754
0
  }
755
615
  return( -1 );
756
13.5k
}
757