Coverage Report

Created: 2025-12-05 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsxfs/libfsxfs/libfsxfs_block_directory.c
Line
Count
Source
1
/*
2
 * Block directory functions
3
 *
4
 * Copyright (C) 2020-2025, 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 "libfsxfs_debug.h"
28
#include "libfsxfs_definitions.h"
29
#include "libfsxfs_directory_entry.h"
30
#include "libfsxfs_block_directory.h"
31
#include "libfsxfs_block_directory_footer.h"
32
#include "libfsxfs_block_directory_header.h"
33
#include "libfsxfs_io_handle.h"
34
#include "libfsxfs_libbfio.h"
35
#include "libfsxfs_libcdata.h"
36
#include "libfsxfs_libcerror.h"
37
#include "libfsxfs_libcnotify.h"
38
39
#include "fsxfs_block_directory.h"
40
41
/* Creates block directory
42
 * Make sure the value block_directory is referencing, is set to NULL
43
 * Returns 1 if successful or -1 on error
44
 */
45
int libfsxfs_block_directory_initialize(
46
     libfsxfs_block_directory_t **block_directory,
47
     size_t block_size,
48
     libcerror_error_t **error )
49
4.52k
{
50
4.52k
  static char *function = "libfsxfs_block_directory_initialize";
51
52
4.52k
  if( block_directory == NULL )
53
0
  {
54
0
    libcerror_error_set(
55
0
     error,
56
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
57
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
58
0
     "%s: invalid block directory.",
59
0
     function );
60
61
0
    return( -1 );
62
0
  }
63
4.52k
  if( *block_directory != NULL )
64
0
  {
65
0
    libcerror_error_set(
66
0
     error,
67
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
68
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
69
0
     "%s: invalid block directory value already set.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
4.52k
  if( ( block_size == 0 )
75
4.52k
   || ( block_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
76
0
  {
77
0
    libcerror_error_set(
78
0
     error,
79
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
80
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
81
0
     "%s: invalid block size value out of bounds.",
82
0
     function );
83
84
0
    return( -1 );
85
0
  }
86
4.52k
  *block_directory = memory_allocate_structure(
87
4.52k
                      libfsxfs_block_directory_t );
88
89
4.52k
  if( *block_directory == NULL )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
94
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
95
0
     "%s: unable to create block directory.",
96
0
     function );
97
98
0
    goto on_error;
99
0
  }
100
4.52k
  if( memory_set(
101
4.52k
       *block_directory,
102
4.52k
       0,
103
4.52k
       sizeof( libfsxfs_block_directory_t ) ) == NULL )
104
0
  {
105
0
    libcerror_error_set(
106
0
     error,
107
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
108
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
109
0
     "%s: unable to clear block directory.",
110
0
     function );
111
112
0
    memory_free(
113
0
     *block_directory );
114
115
0
    *block_directory = NULL;
116
117
0
    return( -1 );
118
0
  }
119
4.52k
  ( *block_directory )->data = (uint8_t *) memory_allocate(
120
4.52k
                                            sizeof( uint8_t ) * block_size );
121
122
4.52k
  if( ( *block_directory )->data == NULL )
123
0
  {
124
0
    libcerror_error_set(
125
0
     error,
126
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
127
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
128
0
     "%s: unable to create block directory data.",
129
0
     function );
130
131
0
    goto on_error;
132
0
  }
133
4.52k
  ( *block_directory )->data_size = block_size;
134
135
4.52k
  return( 1 );
136
137
0
on_error:
138
0
  if( *block_directory != NULL )
139
0
  {
140
0
    memory_free(
141
0
     *block_directory );
142
143
0
    *block_directory = NULL;
144
0
  }
145
0
  return( -1 );
146
4.52k
}
147
148
/* Frees block directory
149
 * Returns 1 if successful or -1 on error
150
 */
151
int libfsxfs_block_directory_free(
152
     libfsxfs_block_directory_t **block_directory,
153
     libcerror_error_t **error )
154
4.52k
{
155
4.52k
  static char *function = "libfsxfs_block_directory_free";
156
4.52k
  int result            = 1;
157
158
4.52k
  if( block_directory == NULL )
159
0
  {
160
0
    libcerror_error_set(
161
0
     error,
162
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
163
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
164
0
     "%s: invalid block directory.",
165
0
     function );
166
167
0
    return( -1 );
168
0
  }
169
4.52k
  if( *block_directory != NULL )
170
4.52k
  {
171
4.52k
    if( ( *block_directory )->footer != NULL )
172
2.06k
    {
173
2.06k
      if( libfsxfs_block_directory_footer_free(
174
2.06k
           &( ( *block_directory )->footer ),
175
2.06k
           error ) != 1 )
176
0
      {
177
0
        libcerror_error_set(
178
0
         error,
179
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
180
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
181
0
         "%s: unable to free footer.",
182
0
         function );
183
184
0
        result = -1;
185
0
      }
186
2.06k
    }
187
4.52k
    if( ( *block_directory )->header != NULL )
188
4.10k
    {
189
4.10k
      if( libfsxfs_block_directory_header_free(
190
4.10k
           &( ( *block_directory )->header ),
191
4.10k
           error ) != 1 )
192
0
      {
193
0
        libcerror_error_set(
194
0
         error,
195
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
196
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
197
0
         "%s: unable to free header.",
198
0
         function );
199
200
0
        result = -1;
201
0
      }
202
4.10k
    }
203
4.52k
    memory_free(
204
4.52k
     ( *block_directory )->data );
205
206
4.52k
    memory_free(
207
4.52k
     *block_directory );
208
209
4.52k
    *block_directory = NULL;
210
4.52k
  }
211
4.52k
  return( result );
212
4.52k
}
213
214
/* Reads the block directory
215
 * Returns 1 if successful or -1 on error
216
 */
217
int libfsxfs_block_directory_read_data(
218
     libfsxfs_block_directory_t *block_directory,
219
     libfsxfs_io_handle_t *io_handle,
220
     const uint8_t *data,
221
     size_t data_size,
222
     libcdata_array_t *entries_array,
223
     libcerror_error_t **error )
224
4.26k
{
225
4.26k
  libfsxfs_directory_entry_t *directory_entry = NULL;
226
4.26k
  static char *function                       = "libfsxfs_block_directory_read_data";
227
4.26k
  size_t alignment_padding_size               = 0;
228
4.26k
  size_t data_offset                          = 0;
229
4.26k
  size_t entries_data_end_offset              = 0;
230
4.26k
  size_t entry_data_size                      = 0;
231
4.26k
  size_t hash_values_data_size                = 0;
232
4.26k
  uint64_t inode_number                       = 0;
233
4.26k
  uint32_t directory_entry_index              = 0;
234
4.26k
  uint16_t free_tag                           = 0;
235
4.26k
  uint8_t name_size                           = 0;
236
4.26k
  int entry_index                             = 0;
237
238
#if defined( HAVE_DEBUG_OUTPUT )
239
  uint16_t value_16bit                        = 0;
240
#endif
241
242
4.26k
  if( block_directory == NULL )
243
0
  {
244
0
    libcerror_error_set(
245
0
     error,
246
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
247
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
248
0
     "%s: invalid block directory.",
249
0
     function );
250
251
0
    return( -1 );
252
0
  }
253
4.26k
  if( block_directory->header != NULL )
254
0
  {
255
0
    libcerror_error_set(
256
0
     error,
257
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
258
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
259
0
     "%s: invalid block directory - header already set.",
260
0
     function );
261
262
0
    return( -1 );
263
0
  }
264
4.26k
  if( block_directory->footer != NULL )
265
0
  {
266
0
    libcerror_error_set(
267
0
     error,
268
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
269
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
270
0
     "%s: invalid block directory - footer already set.",
271
0
     function );
272
273
0
    return( -1 );
274
0
  }
275
4.26k
  if( io_handle == NULL )
276
0
  {
277
0
    libcerror_error_set(
278
0
     error,
279
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
280
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
281
0
     "%s: invalid IO handle.",
282
0
     function );
283
284
0
    return( -1 );
285
0
  }
286
4.26k
  if( data == NULL )
287
0
  {
288
0
    libcerror_error_set(
289
0
     error,
290
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
291
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
292
0
     "%s: invalid data.",
293
0
     function );
294
295
0
    return( -1 );
296
0
  }
297
4.26k
  if( ( data_size < 8 )
298
4.26k
   || ( data_size > (size_t) SSIZE_MAX ) )
299
0
  {
300
0
    libcerror_error_set(
301
0
     error,
302
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
303
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
304
0
     "%s: invalid data size value out of bounds.",
305
0
     function );
306
307
0
    return( -1 );
308
0
  }
309
#if defined( HAVE_DEBUG_OUTPUT )
310
  if( libcnotify_verbose != 0 )
311
  {
312
    libcnotify_printf(
313
     "%s: block directory data:\n",
314
     function );
315
    libcnotify_print_data(
316
     data,
317
     data_size,
318
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
319
  }
320
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
321
322
4.26k
  if( libfsxfs_block_directory_header_initialize(
323
4.26k
       &( block_directory->header ),
324
4.26k
       error ) != 1 )
325
0
  {
326
0
    libcerror_error_set(
327
0
     error,
328
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
329
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
330
0
     "%s: unable to create header.",
331
0
     function );
332
333
0
    goto on_error;
334
0
  }
335
4.26k
  if( libfsxfs_block_directory_header_read_data(
336
4.26k
       block_directory->header,
337
4.26k
       data,
338
4.26k
       data_size,
339
4.26k
       error ) != 1 )
340
45
  {
341
45
    libcerror_error_set(
342
45
     error,
343
45
     LIBCERROR_ERROR_DOMAIN_IO,
344
45
     LIBCERROR_IO_ERROR_READ_FAILED,
345
45
     "%s: unable to read block directory header.",
346
45
     function );
347
348
45
    goto on_error;
349
45
  }
350
4.21k
  if( block_directory->header->has_footer != 0 )
351
2.14k
  {
352
2.14k
    if( libfsxfs_block_directory_footer_initialize(
353
2.14k
         &( block_directory->footer ),
354
2.14k
         error ) != 1 )
355
0
    {
356
0
      libcerror_error_set(
357
0
       error,
358
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
359
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
360
0
       "%s: unable to create footer.",
361
0
       function );
362
363
0
      goto on_error;
364
0
    }
365
2.14k
    if( libfsxfs_block_directory_footer_read_data(
366
2.14k
         block_directory->footer,
367
2.14k
         &( data[ data_size - 8 ] ),
368
2.14k
         8,
369
2.14k
         error ) != 1 )
370
0
    {
371
0
      libcerror_error_set(
372
0
       error,
373
0
       LIBCERROR_ERROR_DOMAIN_IO,
374
0
       LIBCERROR_IO_ERROR_READ_FAILED,
375
0
       "%s: unable to read block directory footer.",
376
0
       function );
377
378
0
      goto on_error;
379
0
    }
380
2.14k
    if( (size_t) block_directory->footer->number_of_entries > ( ( data_size - data_offset - 8 ) / 8 ) )
381
55
    {
382
55
      libcerror_error_set(
383
55
       error,
384
55
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
385
55
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
386
55
       "%s: invalid number of entries value out of bounds.",
387
55
       function );
388
389
55
      goto on_error;
390
55
    }
391
2.08k
    hash_values_data_size = (size_t) block_directory->footer->number_of_entries * 8;
392
393
2.08k
    entries_data_end_offset = data_size - ( 8 + hash_values_data_size );
394
2.08k
  }
395
2.07k
  else
396
2.07k
  {
397
2.07k
    entries_data_end_offset = data_size;
398
2.07k
  }
399
4.16k
  if( block_directory->header->format_version == 3 )
400
2.18k
  {
401
2.18k
    data_offset = sizeof( fsxfs_block_directory_header_v3_t );
402
2.18k
  }
403
1.97k
  else
404
1.97k
  {
405
1.97k
    data_offset = sizeof( fsxfs_block_directory_header_v2_t );
406
1.97k
  }
407
121k
  while( data_offset < entries_data_end_offset )
408
117k
  {
409
117k
    if( ( entries_data_end_offset - data_offset ) < 4 )
410
6
    {
411
6
      libcerror_error_set(
412
6
       error,
413
6
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
414
6
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
415
6
       "%s: invalid data size value out of bounds.",
416
6
       function );
417
418
6
      goto on_error;
419
6
    }
420
117k
    byte_stream_copy_to_uint16_big_endian(
421
117k
     &( data[ data_offset ] ),
422
117k
     free_tag );
423
424
117k
    if( free_tag == 0xffff )
425
3.30k
    {
426
3.30k
      byte_stream_copy_to_uint16_big_endian(
427
3.30k
       &( data[ data_offset + 2 ] ),
428
3.30k
       entry_data_size );
429
430
#if defined( HAVE_DEBUG_OUTPUT )
431
      if( libcnotify_verbose != 0 )
432
      {
433
        libcnotify_printf(
434
         "%s: unused block signature\t\t: 0x%04" PRIx16 "\n",
435
         function,
436
         free_tag );
437
438
        libcnotify_printf(
439
         "%s: entry data size\t\t\t: %" PRIzd "\n",
440
         function,
441
         entry_data_size );
442
443
        libcnotify_printf(
444
         "\n" );
445
      }
446
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
447
448
3.30k
      if( entry_data_size < 4 )
449
9
      {
450
9
        libcerror_error_set(
451
9
         error,
452
9
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
453
9
         LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
454
9
         "%s: invalid data size value out of bounds.",
455
9
         function );
456
457
9
        goto on_error;
458
9
      }
459
3.29k
      data_offset += entry_data_size;
460
461
3.29k
      continue;
462
3.30k
    }
463
114k
    if( ( entries_data_end_offset - data_offset ) < 9 )
464
8
    {
465
8
      libcerror_error_set(
466
8
       error,
467
8
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
468
8
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
469
8
       "%s: invalid data size value out of bounds.",
470
8
       function );
471
472
8
      goto on_error;
473
8
    }
474
114k
    name_size = data[ data_offset + 8 ];
475
476
114k
    entry_data_size = 9 + name_size + 2;
477
478
114k
    if( ( io_handle->format_version == 5 )
479
20.0k
     || ( ( io_handle->secondary_feature_flags & LIBFSXFS_SECONDARY_FEATURE_FLAG_FILE_TYPE ) != 0 ) )
480
103k
    {
481
103k
      entry_data_size++;
482
103k
    }
483
114k
    alignment_padding_size = entry_data_size % 8;
484
485
114k
    if( alignment_padding_size != 0 )
486
110k
    {
487
110k
      alignment_padding_size = 8 - alignment_padding_size;
488
110k
      entry_data_size       += alignment_padding_size;
489
110k
    }
490
114k
    if( ( entry_data_size < 6 )
491
114k
     || ( entry_data_size > ( entries_data_end_offset - data_offset ) ) )
492
32
    {
493
32
      libcerror_error_set(
494
32
       error,
495
32
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
496
32
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
497
32
       "%s: invalid data size value out of bounds.",
498
32
       function );
499
500
32
      goto on_error;
501
32
    }
502
#if defined( HAVE_DEBUG_OUTPUT )
503
    if( libcnotify_verbose != 0 )
504
    {
505
      libcnotify_printf(
506
       "%s: directory entry: %d data:\n",
507
       function,
508
       directory_entry_index );
509
      libcnotify_print_data(
510
       &( data[ data_offset ] ),
511
       entry_data_size,
512
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
513
    }
514
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
515
516
114k
    byte_stream_copy_to_uint64_big_endian(
517
114k
     &( data[ data_offset ] ),
518
114k
     inode_number );
519
520
114k
    data_offset += 9;
521
522
#if defined( HAVE_DEBUG_OUTPUT )
523
    if( libcnotify_verbose != 0 )
524
    {
525
      libcnotify_printf(
526
       "%s: inode number\t\t\t: %" PRIu64 "\n",
527
       function,
528
       inode_number );
529
530
      libcnotify_printf(
531
       "%s: name size\t\t\t\t: %" PRIu8 "\n",
532
       function,
533
       name_size );
534
535
      if( libfsxfs_debug_print_utf8_string_value(
536
           function,
537
           "name\t\t\t\t",
538
           &( data[ data_offset ] ),
539
           name_size,
540
           error ) != 1 )
541
      {
542
        libcerror_error_set(
543
         error,
544
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
545
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
546
         "%s: unable to print UTF-8 string value.",
547
         function );
548
549
        goto on_error;
550
      }
551
    }
552
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
553
554
114k
    if( ( name_size == 1 )
555
5.05k
     && ( data[ data_offset ] == '.' ) )
556
924
    {
557
      /* Ignore self directory entry "." */
558
924
    }
559
113k
    else if( ( name_size == 2 )
560
7.80k
          && ( data[ data_offset ] == '.' )
561
1.41k
          && ( data[ data_offset + 1 ] == '.' ) )
562
556
    {
563
      /* Ignore parent directory entry ".." */
564
556
    }
565
112k
    else
566
112k
    {
567
112k
      if( libfsxfs_directory_entry_initialize(
568
112k
           &directory_entry,
569
112k
           error ) != 1 )
570
0
      {
571
0
        libcerror_error_set(
572
0
         error,
573
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
574
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
575
0
         "%s: unable to create directory entry: %d.",
576
0
         function,
577
0
         directory_entry_index );
578
579
0
        goto on_error;
580
0
      }
581
112k
      directory_entry->inode_number = inode_number;
582
583
112k
      if( memory_copy(
584
112k
           directory_entry->name,
585
112k
           &( data[ data_offset ] ),
586
112k
           (size_t) name_size ) == NULL )
587
0
      {
588
0
        libcerror_error_set(
589
0
         error,
590
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
591
0
         LIBCERROR_MEMORY_ERROR_COPY_FAILED,
592
0
         "%s: unable to copy name.",
593
0
         function );
594
595
0
        goto on_error;
596
0
      }
597
112k
      directory_entry->name_size = name_size;
598
112k
    }
599
114k
    data_offset += name_size;
600
601
114k
    if( ( io_handle->format_version == 5 )
602
20.0k
     || ( ( io_handle->secondary_feature_flags & LIBFSXFS_SECONDARY_FEATURE_FLAG_FILE_TYPE ) != 0 ) )
603
103k
    {
604
#if defined( HAVE_DEBUG_OUTPUT )
605
      if( libcnotify_verbose != 0 )
606
      {
607
        libcnotify_printf(
608
         "%s: file type\t\t\t\t: %" PRIu8 "\n",
609
         function,
610
         data[ data_offset ] );
611
      }
612
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
613
614
103k
      data_offset++;
615
103k
    }
616
114k
    if( alignment_padding_size > 0 )
617
110k
    {
618
#if defined( HAVE_DEBUG_OUTPUT )
619
      if( libcnotify_verbose != 0 )
620
      {
621
        libcnotify_printf(
622
         "%s: alignment padding:\n",
623
         function,
624
         directory_entry_index );
625
        libcnotify_print_data(
626
         &( data[ data_offset ] ),
627
         alignment_padding_size,
628
         0 );
629
      }
630
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
631
632
110k
      data_offset += alignment_padding_size;
633
110k
    }
634
114k
    if( directory_entry != NULL )
635
112k
    {
636
112k
      if( libcdata_array_append_entry(
637
112k
           entries_array,
638
112k
           &entry_index,
639
112k
           (intptr_t *) directory_entry,
640
112k
           error ) != 1 )
641
0
      {
642
0
        libcerror_error_set(
643
0
         error,
644
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
645
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
646
0
         "%s: unable to append directory entry to entries array.",
647
0
         function );
648
649
0
        goto on_error;
650
0
      }
651
112k
      directory_entry = NULL;
652
112k
    }
653
#if defined( HAVE_DEBUG_OUTPUT )
654
    if( libcnotify_verbose != 0 )
655
    {
656
      byte_stream_copy_to_uint16_big_endian(
657
       &( data[ data_offset ] ),
658
       value_16bit );
659
      libcnotify_printf(
660
       "%s: tag offset\t\t\t\t: %" PRIu16 "\n",
661
       function,
662
       value_16bit );
663
664
      libcnotify_printf(
665
       "\n" );
666
    }
667
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
668
669
114k
    data_offset += 2;
670
671
114k
    directory_entry_index++;
672
114k
  }
673
4.10k
  if( hash_values_data_size > 0 )
674
527
  {
675
#if defined( HAVE_DEBUG_OUTPUT )
676
    if( libcnotify_verbose != 0 )
677
    {
678
      libcnotify_printf(
679
       "%s: hash values data:\n",
680
       function );
681
      libcnotify_print_data(
682
       &( data[ entries_data_end_offset ] ),
683
       hash_values_data_size,
684
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
685
    }
686
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
687
527
  }
688
4.10k
  return( 1 );
689
690
155
on_error:
691
155
  if( directory_entry != NULL )
692
0
  {
693
0
    libfsxfs_directory_entry_free(
694
0
     &directory_entry,
695
0
     NULL );
696
0
  }
697
155
  if( block_directory->footer != NULL )
698
73
  {
699
73
    libfsxfs_block_directory_footer_free(
700
73
     &( block_directory->footer ),
701
73
     NULL );
702
73
  }
703
155
  if( block_directory->header != NULL )
704
155
  {
705
155
    libfsxfs_block_directory_header_free(
706
155
     &( block_directory->header ),
707
155
     NULL );
708
155
  }
709
155
  libcdata_array_empty(
710
155
   entries_array,
711
155
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsxfs_directory_entry_free,
712
155
   NULL );
713
714
155
  return( -1 );
715
4.16k
}
716
717
/* Reads the block directory from a Basic File IO (bfio) handle
718
 * Returns 1 if successful or -1 on error
719
 */
720
int libfsxfs_block_directory_read_file_io_handle(
721
     libfsxfs_block_directory_t *block_directory,
722
     libfsxfs_io_handle_t *io_handle,
723
     libbfio_handle_t *file_io_handle,
724
     off64_t file_offset,
725
     libcdata_array_t *entries_array,
726
     libcerror_error_t **error )
727
4.52k
{
728
4.52k
  static char *function = "libfsxfs_block_directory_read_file_io_handle";
729
4.52k
  ssize_t read_count    = 0;
730
731
4.52k
  if( block_directory == NULL )
732
0
  {
733
0
    libcerror_error_set(
734
0
     error,
735
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
736
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
737
0
     "%s: invalid block directory.",
738
0
     function );
739
740
0
    return( -1 );
741
0
  }
742
4.52k
  if( block_directory->header != NULL )
743
0
  {
744
0
    libcerror_error_set(
745
0
     error,
746
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
747
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
748
0
     "%s: invalid block directory - header value already set.",
749
0
     function );
750
751
0
    return( -1 );
752
0
  }
753
#if defined( HAVE_DEBUG_OUTPUT )
754
  if( libcnotify_verbose != 0 )
755
  {
756
    libcnotify_printf(
757
     "%s: reading block directory at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
758
     function,
759
     file_offset,
760
     file_offset );
761
  }
762
#endif
763
4.52k
  read_count = libbfio_handle_read_buffer_at_offset(
764
4.52k
                file_io_handle,
765
4.52k
                block_directory->data,
766
4.52k
                block_directory->data_size,
767
4.52k
                file_offset,
768
4.52k
                error );
769
770
4.52k
  if( read_count != (ssize_t) block_directory->data_size )
771
269
  {
772
269
    libcerror_error_set(
773
269
     error,
774
269
     LIBCERROR_ERROR_DOMAIN_IO,
775
269
     LIBCERROR_IO_ERROR_READ_FAILED,
776
269
     "%s: unable to read block directory data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
777
269
     function,
778
269
     file_offset,
779
269
     file_offset );
780
781
269
    return( -1 );
782
269
  }
783
4.26k
  if( libfsxfs_block_directory_read_data(
784
4.26k
       block_directory,
785
4.26k
       io_handle,
786
4.26k
       block_directory->data,
787
4.26k
       block_directory->data_size,
788
4.26k
       entries_array,
789
4.26k
       error ) != 1 )
790
155
  {
791
155
    libcerror_error_set(
792
155
     error,
793
155
     LIBCERROR_ERROR_DOMAIN_IO,
794
155
     LIBCERROR_IO_ERROR_READ_FAILED,
795
155
     "%s: unable to read block directory at offset: %" PRIi64 " (0x%08" PRIx64 ").",
796
155
     function,
797
155
     file_offset,
798
155
     file_offset );
799
800
155
    return( -1 );
801
155
  }
802
4.10k
  return( 1 );
803
4.26k
}
804