Coverage Report

Created: 2025-06-22 07:35

/src/libolecf/libolecf/libolecf_io_handle.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Input/Output (IO) handle 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 "libolecf_allocation_table.h"
28
#include "libolecf_codepage.h"
29
#include "libolecf_debug.h"
30
#include "libolecf_definitions.h"
31
#include "libolecf_directory_entry.h"
32
#include "libolecf_io_handle.h"
33
#include "libolecf_libbfio.h"
34
#include "libolecf_libcdata.h"
35
#include "libolecf_libcerror.h"
36
#include "libolecf_libcnotify.h"
37
#include "libolecf_libfguid.h"
38
#include "libolecf_libuna.h"
39
#include "libolecf_notify.h"
40
41
#include "olecf_directory.h"
42
#include "olecf_file_header.h"
43
44
const uint8_t olecf_file_signature[ 8 ]      = { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
45
const uint8_t olecf_beta_file_signature[ 8 ] = { 0x0e, 0x11, 0xfc, 0x0d, 0xd0, 0xcf, 0x11, 0x0e };
46
47
/* Creates an IO handle
48
 * Make sure the value io_handle is referencing, is set to NULL
49
 * Returns 1 if successful or -1 on error
50
 */
51
int libolecf_io_handle_initialize(
52
     libolecf_io_handle_t **io_handle,
53
     libcerror_error_t **error )
54
1.88k
{
55
1.88k
  static char *function = "libolecf_io_handle_initialize";
56
57
1.88k
  if( io_handle == 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 IO handle.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
1.88k
  if( *io_handle != 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 IO handle value already set.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
1.88k
  *io_handle = memory_allocate_structure(
80
1.88k
                libolecf_io_handle_t );
81
82
1.88k
  if( *io_handle == NULL )
83
0
  {
84
0
    libcerror_error_set(
85
0
     error,
86
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
87
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
88
0
     "%s: unable to create IO handle.",
89
0
     function );
90
91
0
    goto on_error;
92
0
  }
93
1.88k
  if( memory_set(
94
1.88k
       *io_handle,
95
1.88k
       0,
96
1.88k
       sizeof( libolecf_io_handle_t ) ) == NULL )
97
0
  {
98
0
    libcerror_error_set(
99
0
     error,
100
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
101
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
102
0
     "%s: unable to clear IO handle.",
103
0
     function );
104
105
0
    memory_free(
106
0
     *io_handle );
107
108
0
    *io_handle = NULL;
109
110
0
    return( -1 );
111
0
  }
112
1.88k
  ( *io_handle )->ascii_codepage = LIBOLECF_CODEPAGE_WINDOWS_1252;
113
114
1.88k
  return( 1 );
115
116
0
on_error:
117
0
  if( *io_handle != NULL )
118
0
  {
119
0
    memory_free(
120
0
     *io_handle );
121
122
0
    *io_handle = NULL;
123
0
  }
124
0
  return( -1 );
125
1.88k
}
126
127
/* Frees an IO handle
128
 * Returns 1 if successful or -1 on error
129
 */
130
int libolecf_io_handle_free(
131
     libolecf_io_handle_t **io_handle,
132
     libcerror_error_t **error )
133
1.88k
{
134
1.88k
  static char *function = "libolecf_io_handle_free";
135
1.88k
  int result            = 1;
136
137
1.88k
  if( io_handle == NULL )
138
0
  {
139
0
    libcerror_error_set(
140
0
     error,
141
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
142
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
143
0
     "%s: invalid IO handle.",
144
0
     function );
145
146
0
    return( -1 );
147
0
  }
148
1.88k
  if( *io_handle != NULL )
149
1.88k
  {
150
1.88k
    memory_free(
151
1.88k
     *io_handle );
152
153
1.88k
    *io_handle = NULL;
154
1.88k
  }
155
1.88k
  return( result );
156
1.88k
}
157
158
/* Clears an IO handle
159
 * Returns 1 if successful or -1 on error
160
 */
161
int libolecf_io_handle_clear(
162
     libolecf_io_handle_t *io_handle,
163
     libcerror_error_t **error )
164
160
{
165
160
  static char *function = "libolecf_io_handle_clear";
166
167
160
  if( io_handle == NULL )
168
0
  {
169
0
    libcerror_error_set(
170
0
     error,
171
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
172
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
173
0
     "%s: invalid IO handle.",
174
0
     function );
175
176
0
    return( -1 );
177
0
  }
178
160
  if( memory_set(
179
160
       io_handle,
180
160
       0,
181
160
       sizeof( libolecf_io_handle_t ) ) == NULL )
182
0
  {
183
0
    libcerror_error_set(
184
0
     error,
185
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
186
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
187
0
     "%s: unable to clear IO handle.",
188
0
     function );
189
190
0
    return( -1 );
191
0
  }
192
160
  io_handle->ascii_codepage = LIBOLECF_CODEPAGE_WINDOWS_1252;
193
194
160
  return( 1 );
195
160
}
196
197
/* Reads the MSAT
198
 * This function assumes the first 109 MSAT sector identifiers in the file header are read into the MSAT
199
 * Returns 1 if successful or -1 on error
200
 */
201
int libolecf_io_handle_read_msat(
202
     libolecf_io_handle_t *io_handle,
203
     libbfio_handle_t *file_io_handle,
204
     libolecf_allocation_table_t *msat,
205
     uint32_t msat_sector_identifier,
206
     uint32_t number_of_msat_sectors,
207
     libcerror_error_t **error )
208
1.62k
{
209
1.62k
  uint8_t *msat_sector                 = NULL;
210
1.62k
  uint8_t *msat_entry                  = NULL;
211
1.62k
  static char *function                = "libolecf_io_handle_read_msat";
212
1.62k
  off64_t msat_sector_offset           = 0;
213
1.62k
  size_t number_of_msat_sector_entries = 0;
214
1.62k
  ssize_t read_count                   = 0;
215
1.62k
  int number_of_msat_entries           = 0;
216
1.62k
  int msat_index                       = 109;
217
1.62k
  int msat_sector_index                = 0;
218
1.62k
  int recursion_depth                  = 0;
219
220
1.62k
  if( io_handle == NULL )
221
0
  {
222
0
    libcerror_error_set(
223
0
     error,
224
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
225
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
226
0
     "%s: invalid IO handle.",
227
0
     function );
228
229
0
    return( -1 );
230
0
  }
231
1.62k
  if( ( io_handle->sector_size == 0 )
232
1.62k
   || ( io_handle->sector_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
233
0
  {
234
0
    libcerror_error_set(
235
0
     error,
236
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
237
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
238
0
     "%s: invalid IO handle - sector size value out of bounds.",
239
0
     function );
240
241
0
    return( -1 );
242
0
  }
243
1.62k
  if( msat == NULL )
244
0
  {
245
0
    libcerror_error_set(
246
0
     error,
247
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
248
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
249
0
     "%s: invalid MSAT.",
250
0
     function );
251
252
0
    return( -1 );
253
0
  }
254
1.62k
  if( msat->number_of_sector_identifiers < 109 )
255
0
  {
256
0
    libcerror_error_set(
257
0
     error,
258
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
259
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
260
0
     "%s: invalid IO handle - invalid MSAT - number of sector identifiers too small.",
261
0
     function );
262
263
0
    return( -1 );
264
0
  }
265
  /* Check if the MSAT is already fully read
266
   */
267
1.62k
  if( ( msat_sector_identifier == LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
268
1.62k
   && ( number_of_msat_sectors == 0 ) )
269
295
  {
270
295
    return( 1 );
271
295
  }
272
1.33k
  if( msat_sector_identifier == LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
273
72
  {
274
72
    libcerror_error_set(
275
72
     error,
276
72
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
277
72
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
278
72
     "%s: invalid MSAT sector identifier.",
279
72
     function );
280
281
72
    return( -1 );
282
72
  }
283
1.26k
  if( number_of_msat_sectors == 0 )
284
330
  {
285
#if defined( HAVE_VERBOSE_OUTPUT ) || defined( HAVE_DEBUG_OUTPUT )
286
    if( libcnotify_verbose != 0 )
287
    {
288
      libcnotify_printf(
289
       "%s: mismatch between number of MSAT sectors and MSAT sector identifier\n",
290
       function );
291
    }
292
#endif
293
330
    number_of_msat_sectors = 1;
294
330
  }
295
1.26k
  number_of_msat_sector_entries = io_handle->sector_size / 4;
296
297
1.26k
  if( number_of_msat_sector_entries == 0 )
298
3
  {
299
3
    libcerror_error_set(
300
3
     error,
301
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
302
3
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
303
3
     "%s: invalid number of MSAT sector entries value out of bounds.",
304
3
     function );
305
306
3
    goto on_error;
307
3
  }
308
  /* The last MSAT entry is reserved for the next MSAT sector identifier.
309
   */
310
1.25k
  number_of_msat_sector_entries -= 1;
311
312
1.25k
  number_of_msat_entries = 109 + ( number_of_msat_sectors * number_of_msat_sector_entries );
313
314
1.25k
  if( msat->number_of_sector_identifiers < number_of_msat_entries )
315
560
  {
316
560
    if( libolecf_allocation_table_resize(
317
560
         msat,
318
560
         number_of_msat_entries,
319
560
         error ) != 1 )
320
2
    {
321
2
      libcerror_error_set(
322
2
       error,
323
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
324
2
       LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
325
2
       "%s: unable to resize MSAT.",
326
2
       function );
327
328
2
      goto on_error;
329
2
    }
330
560
  }
331
1.25k
  msat_sector = (uint8_t *) memory_allocate(
332
1.25k
                             sizeof( uint8_t ) * io_handle->sector_size );
333
334
1.25k
  if( msat_sector == NULL )
335
0
  {
336
0
    libcerror_error_set(
337
0
     error,
338
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
339
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
340
0
     "%s: unable to create MSAT sector.",
341
0
     function );
342
343
0
    goto on_error;
344
0
  }
345
15.4k
  while( msat_sector_identifier != LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
346
15.3k
  {
347
15.3k
    if( recursion_depth > LIBOLECF_MAXIMUM_ALLOCATION_TABLE_RECURSION_DEPTH )
348
11
    {
349
11
      libcerror_error_set(
350
11
       error,
351
11
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
352
11
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
353
11
       "%s: invalid recursion depth value out of bounds.",
354
11
       function );
355
356
11
      goto on_error;
357
11
    }
358
15.3k
    recursion_depth++;
359
360
15.3k
    if( msat_index >= msat->number_of_sector_identifiers )
361
1.14k
    {
362
1.14k
      break;
363
1.14k
    }
364
14.2k
    msat_sector_offset = ( msat_sector_identifier + 1 ) * io_handle->sector_size;
365
366
#if defined( HAVE_DEBUG_OUTPUT )
367
    if( libcnotify_verbose != 0 )
368
    {
369
      libcnotify_printf(
370
       "%s: MSAT sector offset\t\t\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
371
       function,
372
       msat_sector_offset,
373
       msat_sector_offset );
374
    }
375
#endif
376
14.2k
    read_count = libbfio_handle_read_buffer_at_offset(
377
14.2k
            file_io_handle,
378
14.2k
            msat_sector,
379
14.2k
            io_handle->sector_size,
380
14.2k
            msat_sector_offset,
381
14.2k
            error );
382
383
14.2k
    if( read_count != (ssize_t) io_handle->sector_size )
384
46
    {
385
46
      libcerror_error_set(
386
46
       error,
387
46
       LIBCERROR_ERROR_DOMAIN_IO,
388
46
       LIBCERROR_IO_ERROR_READ_FAILED,
389
46
       "%s: unable to read MSAT sector at offset: %" PRIi64 " (0x%08" PRIx64 ").",
390
46
       function,
391
46
       msat_sector_offset,
392
46
       msat_sector_offset );
393
394
46
      goto on_error;
395
46
    }
396
#if defined( HAVE_DEBUG_OUTPUT )
397
    if( libcnotify_verbose != 0 )
398
    {
399
      libcnotify_printf(
400
       "%s: MSAT sector:\n",
401
       function );
402
      libcnotify_print_data(
403
       msat_sector,
404
       io_handle->sector_size,
405
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
406
    }
407
#endif
408
14.1k
    msat_entry = msat_sector;
409
410
14.1k
    for( msat_sector_index = 0;
411
10.4M
         (size_t) msat_sector_index < number_of_msat_sector_entries;
412
10.4M
         msat_sector_index++ )
413
10.4M
    {
414
10.4M
      if( ( msat_index < 0 )
415
10.4M
       || ( msat_index >= msat->number_of_sector_identifiers ) )
416
6
      {
417
6
        libcerror_error_set(
418
6
         error,
419
6
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
420
6
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
421
6
         "%s: invalid MSAT entry: %04d value out of bounds.",
422
6
         function,
423
6
         msat_index );
424
425
6
        goto on_error;
426
6
      }
427
10.4M
      if( io_handle->byte_order == LIBOLECF_ENDIAN_LITTLE )
428
7.71M
      {
429
7.71M
        byte_stream_copy_to_uint32_little_endian(
430
7.71M
         msat_entry,
431
7.71M
         msat->sector_identifiers[ msat_index ] );
432
7.71M
      }
433
2.73M
      else if( io_handle->byte_order == LIBOLECF_ENDIAN_BIG )
434
2.73M
      {
435
2.73M
        byte_stream_copy_to_uint32_big_endian(
436
2.73M
         msat_entry,
437
2.73M
         msat->sector_identifiers[ msat_index ] );
438
2.73M
      }
439
#if defined( HAVE_DEBUG_OUTPUT )
440
      if( libcnotify_verbose != 0 )
441
      {
442
        libcnotify_printf(
443
         "%s: MSAT entry: %03d sector identifier\t: 0x%08" PRIx32 "\n",
444
         function,
445
         msat_index,
446
         msat->sector_identifiers[ msat_index ] );
447
      }
448
#endif
449
10.4M
      msat_entry += 4;
450
451
10.4M
      msat_index++;
452
10.4M
    }
453
14.1k
    if( io_handle->byte_order == LIBOLECF_ENDIAN_LITTLE )
454
10.4k
    {
455
10.4k
      byte_stream_copy_to_uint32_little_endian(
456
10.4k
       msat_entry,
457
10.4k
       msat_sector_identifier );
458
10.4k
    }
459
3.74k
    else if( io_handle->byte_order == LIBOLECF_ENDIAN_BIG )
460
3.74k
    {
461
3.74k
      byte_stream_copy_to_uint32_big_endian(
462
3.74k
       msat_entry,
463
3.74k
       msat_sector_identifier );
464
3.74k
    }
465
#if defined( HAVE_DEBUG_OUTPUT )
466
    if( libcnotify_verbose != 0 )
467
    {
468
      libcnotify_printf(
469
       "%s: MSAT sector identifier\t\t: 0x%08" PRIx32 "\n",
470
       function,
471
       msat_sector_identifier );
472
      libcnotify_printf(
473
       "\n" );
474
    }
475
#endif
476
14.1k
  }
477
1.19k
  memory_free(
478
1.19k
   msat_sector );
479
480
1.19k
  return( 1 );
481
482
68
on_error:
483
68
  if( msat_sector != NULL )
484
63
  {
485
63
    memory_free(
486
63
     msat_sector );
487
63
  }
488
68
  return( -1 );
489
490
1.25k
}
491
492
/* Reads the SAT
493
 * This function requires that the MSAT was read
494
 * Returns 1 if successful or -1 on error
495
 */
496
int libolecf_io_handle_read_sat(
497
     libolecf_io_handle_t *io_handle,
498
     libbfio_handle_t *file_io_handle,
499
     libolecf_allocation_table_t *msat,
500
     libolecf_allocation_table_t *sat,
501
     uint32_t number_of_sat_sectors,
502
     libcerror_error_t **error )
503
1.48k
{
504
1.48k
  uint8_t *sat_sector                 = NULL;
505
1.48k
  uint8_t *sat_entry                  = NULL;
506
1.48k
  static char *function               = "libolecf_io_handle_read_sat";
507
1.48k
  off64_t sat_sector_offset           = 0;
508
1.48k
  size_t number_of_sat_sector_entries = 0;
509
1.48k
  ssize_t read_count                  = 0;
510
1.48k
  int number_of_sat_entries           = 0;
511
1.48k
  int msat_index                      = 0;
512
1.48k
  int sat_index                       = 0;
513
1.48k
  int sat_sector_index                = 0;
514
515
1.48k
  if( io_handle == NULL )
516
0
  {
517
0
    libcerror_error_set(
518
0
     error,
519
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
520
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
521
0
     "%s: invalid IO handle.",
522
0
     function );
523
524
0
    return( -1 );
525
0
  }
526
1.48k
  if( ( io_handle->sector_size == 0 )
527
1.48k
   || ( io_handle->sector_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
528
0
  {
529
0
    libcerror_error_set(
530
0
     error,
531
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
532
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
533
0
     "%s: invalid IO handle - sector size value out of bounds.",
534
0
     function );
535
536
0
    return( -1 );
537
0
  }
538
1.48k
  if( msat == NULL )
539
0
  {
540
0
    libcerror_error_set(
541
0
     error,
542
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
543
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
544
0
     "%s: invalid MSAT.",
545
0
     function );
546
547
0
    return( -1 );
548
0
  }
549
1.48k
  if( sat == NULL )
550
0
  {
551
0
    libcerror_error_set(
552
0
     error,
553
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
554
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
555
0
     "%s: invalid SAT.",
556
0
     function );
557
558
0
    return( -1 );
559
0
  }
560
1.48k
  number_of_sat_sector_entries = io_handle->sector_size / 4;
561
1.48k
  number_of_sat_entries        = number_of_sat_sectors * number_of_sat_sector_entries;
562
563
1.48k
  if( sat->number_of_sector_identifiers < number_of_sat_entries )
564
1.36k
  {
565
1.36k
    if( libolecf_allocation_table_resize(
566
1.36k
         sat,
567
1.36k
         number_of_sat_entries,
568
1.36k
         error ) != 1 )
569
20
    {
570
20
      libcerror_error_set(
571
20
       error,
572
20
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
573
20
       LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
574
20
       "%s: unable to resize SAT.",
575
20
       function );
576
577
20
      goto on_error;
578
20
    }
579
1.36k
  }
580
1.46k
  sat_sector = (uint8_t *) memory_allocate(
581
1.46k
                            sizeof( uint8_t ) * io_handle->sector_size );
582
583
1.46k
  if( sat_sector == NULL )
584
0
  {
585
0
    libcerror_error_set(
586
0
     error,
587
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
588
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
589
0
     "%s: unable to create SAT sector.",
590
0
     function );
591
592
0
    goto on_error;
593
0
  }
594
1.46k
  for( msat_index = 0;
595
27.1k
       msat_index < msat->number_of_sector_identifiers;
596
25.6k
       msat_index++ )
597
27.1k
  {
598
#if defined( HAVE_DEBUG_OUTPUT )
599
    if( libcnotify_verbose != 0 )
600
    {
601
      libcnotify_printf(
602
       "%s: MSAT entry: %03d sector identifier\t\t: 0x%08" PRIx32 "\n",
603
       function,
604
       msat_index,
605
       msat->sector_identifiers[ msat_index ] );
606
    }
607
#endif
608
    /* Skip empty sector identifiers
609
     */
610
27.1k
    if( msat->sector_identifiers[ msat_index ] == LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
611
15.5k
    {
612
#if defined( HAVE_DEBUG_OUTPUT )
613
      if( libcnotify_verbose != 0 )
614
      {
615
        libcnotify_printf(
616
         "\n" );
617
      }
618
#endif
619
15.5k
      continue;
620
15.5k
    }
621
11.5k
    if( sat_index >= sat->number_of_sector_identifiers )
622
247
    {
623
247
      break;
624
247
    }
625
11.3k
    sat_sector_offset = ( msat->sector_identifiers[ msat_index ] + 1 ) * io_handle->sector_size;
626
627
#if defined( HAVE_DEBUG_OUTPUT )
628
    if( libcnotify_verbose != 0 )
629
    {
630
      libcnotify_printf(
631
       "%s: SAT sector offset\t\t\t\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
632
       function,
633
       sat_sector_offset,
634
       sat_sector_offset );
635
    }
636
#endif
637
11.3k
    read_count = libbfio_handle_read_buffer_at_offset(
638
11.3k
            file_io_handle,
639
11.3k
            sat_sector,
640
11.3k
            io_handle->sector_size,
641
11.3k
            sat_sector_offset,
642
11.3k
            error );
643
644
11.3k
    if( read_count != (ssize_t) io_handle->sector_size )
645
1.21k
    {
646
1.21k
      libcerror_error_set(
647
1.21k
       error,
648
1.21k
       LIBCERROR_ERROR_DOMAIN_IO,
649
1.21k
       LIBCERROR_IO_ERROR_READ_FAILED,
650
1.21k
       "%s: unable to read SAT sector at offset: %" PRIi64 " (0x%08" PRIx64 ").",
651
1.21k
       function,
652
1.21k
       sat_sector_offset,
653
1.21k
       sat_sector_offset );
654
655
1.21k
      goto on_error;
656
1.21k
    }
657
#if defined( HAVE_DEBUG_OUTPUT )
658
    if( libcnotify_verbose != 0 )
659
    {
660
      libcnotify_printf(
661
       "%s: SAT sector:\n",
662
       function );
663
      libcnotify_print_data(
664
       sat_sector,
665
       io_handle->sector_size,
666
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
667
    }
668
#endif
669
10.1k
    sat_entry = sat_sector;
670
671
10.1k
    for( sat_sector_index = 0;
672
493k
         (size_t) sat_sector_index < number_of_sat_sector_entries;
673
483k
         sat_sector_index++ )
674
483k
    {
675
483k
      if( io_handle->byte_order == LIBOLECF_ENDIAN_LITTLE )
676
367k
      {
677
367k
        byte_stream_copy_to_uint32_little_endian(
678
367k
         sat_entry,
679
367k
         sat->sector_identifiers[ sat_index ] );
680
367k
      }
681
116k
      else if( io_handle->byte_order == LIBOLECF_ENDIAN_BIG )
682
116k
      {
683
116k
        byte_stream_copy_to_uint32_big_endian(
684
116k
         sat_entry,
685
116k
         sat->sector_identifiers[ sat_index ] );
686
116k
      }
687
#if defined( HAVE_DEBUG_OUTPUT )
688
      if( libcnotify_verbose != 0 )
689
      {
690
        libcnotify_printf(
691
         "%s: SAT entry: %04d sector identifier\t\t: 0x%08" PRIx32 "\n",
692
         function,
693
         sat_index,
694
         sat->sector_identifiers[ sat_index ] );
695
      }
696
#endif
697
483k
      sat_entry += 4;
698
699
483k
      sat_index++;
700
483k
    }
701
#if defined( HAVE_DEBUG_OUTPUT )
702
    if( libcnotify_verbose != 0 )
703
    {
704
      libcnotify_printf(
705
       "\n" );
706
    }
707
#endif
708
10.1k
  }
709
253
  memory_free(
710
253
   sat_sector );
711
712
253
  return( 1 );
713
714
1.23k
on_error:
715
1.23k
  if( sat_sector != NULL )
716
1.21k
  {
717
1.21k
    memory_free(
718
1.21k
     sat_sector );
719
1.21k
  }
720
1.23k
  return( 1 );
721
1.46k
}
722
723
/* Reads the SSAT
724
 * This function requires that the SAT was read
725
 * Returns 1 if successful or -1 on error
726
 */
727
int libolecf_io_handle_read_ssat(
728
     libolecf_io_handle_t *io_handle,
729
     libbfio_handle_t *file_io_handle,
730
     libolecf_allocation_table_t *sat,
731
     libolecf_allocation_table_t *ssat,
732
     uint32_t ssat_sector_identifier,
733
     uint32_t number_of_ssat_sectors,
734
     libcerror_error_t **error )
735
1.48k
{
736
1.48k
  uint8_t *ssat_sector                 = NULL;
737
1.48k
  uint8_t *ssat_entry                  = NULL;
738
1.48k
  static char *function                = "libolecf_io_handle_read_ssat";
739
1.48k
  off64_t ssat_sector_offset           = 0;
740
1.48k
  size_t number_of_ssat_sector_entries = 0;
741
1.48k
  ssize_t read_count                   = 0;
742
1.48k
  uint32_t ssat_sector_index           = 0;
743
1.48k
  int number_of_ssat_entries           = 0;
744
1.48k
  int recursion_depth                  = 0;
745
1.48k
  int ssat_index                       = 0;
746
1.48k
  int ssat_sector_entry_index          = 0;
747
748
1.48k
  if( io_handle == NULL )
749
0
  {
750
0
    libcerror_error_set(
751
0
     error,
752
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
753
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
754
0
     "%s: invalid IO handle.",
755
0
     function );
756
757
0
    return( -1 );
758
0
  }
759
1.48k
  if( ( io_handle->sector_size == 0 )
760
1.48k
   || ( io_handle->sector_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
761
0
  {
762
0
    libcerror_error_set(
763
0
     error,
764
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
765
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
766
0
     "%s: invalid IO handle - sector size value out of bounds.",
767
0
     function );
768
769
0
    return( -1 );
770
0
  }
771
1.48k
  if( sat == NULL )
772
0
  {
773
0
    libcerror_error_set(
774
0
     error,
775
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
776
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
777
0
     "%s: invalid SAT.",
778
0
     function );
779
780
0
    return( -1 );
781
0
  }
782
1.48k
  if( ssat == NULL )
783
0
  {
784
0
    libcerror_error_set(
785
0
     error,
786
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
787
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
788
0
     "%s: invalid SSAT.",
789
0
     function );
790
791
0
    return( -1 );
792
0
  }
793
1.48k
  number_of_ssat_sector_entries = io_handle->sector_size / 4;
794
1.48k
  number_of_ssat_entries        = number_of_ssat_sectors * number_of_ssat_sector_entries;
795
796
1.48k
  if( ssat->number_of_sector_identifiers < number_of_ssat_entries )
797
960
  {
798
960
    if( libolecf_allocation_table_resize(
799
960
         ssat,
800
960
         number_of_ssat_entries,
801
960
         error ) != 1 )
802
106
    {
803
106
      libcerror_error_set(
804
106
       error,
805
106
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
806
106
       LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
807
106
       "%s: unable to resize SSAT.",
808
106
       function );
809
810
106
      goto on_error;
811
106
    }
812
960
  }
813
1.38k
  ssat_sector = (uint8_t *) memory_allocate(
814
1.38k
                             sizeof( uint8_t ) * io_handle->sector_size );
815
816
1.38k
  if( ssat_sector == NULL )
817
0
  {
818
0
    libcerror_error_set(
819
0
     error,
820
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
821
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
822
0
     "%s: unable to create SSAT sector.",
823
0
     function );
824
825
0
    goto on_error;
826
0
  }
827
42.7k
  while( ssat_sector_identifier != LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
828
42.7k
  {
829
42.7k
    if( recursion_depth > LIBOLECF_MAXIMUM_ALLOCATION_TABLE_RECURSION_DEPTH )
830
129
    {
831
129
      libcerror_error_set(
832
129
       error,
833
129
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
834
129
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
835
129
       "%s: invalid recursion depth value out of bounds.",
836
129
       function );
837
838
129
      goto on_error;
839
129
    }
840
42.5k
    recursion_depth++;
841
842
#if defined( HAVE_DEBUG_OUTPUT )
843
    if( libcnotify_verbose != 0 )
844
    {
845
      libcnotify_printf(
846
       "%s: SSAT sector identifier\t\t\t: 0x%08" PRIx32 "\n",
847
       function,
848
       ssat_sector_identifier );
849
    }
850
#endif
851
42.5k
    if( ssat_sector_index >= number_of_ssat_sectors )
852
240
    {
853
240
      break;
854
240
    }
855
    /* Skip empty sector identifiers
856
     */
857
42.3k
    if( ssat_sector_identifier == LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
858
12.8k
    {
859
#if defined( HAVE_DEBUG_OUTPUT )
860
      if( libcnotify_verbose != 0 )
861
      {
862
        libcnotify_printf(
863
         "\n" );
864
      }
865
#endif
866
12.8k
      ssat_sector_index++;
867
868
12.8k
      continue;
869
12.8k
    }
870
29.5k
    ssat_sector_offset = ( ssat_sector_identifier + 1 ) * io_handle->sector_size;
871
872
#if defined( HAVE_DEBUG_OUTPUT )
873
    if( libcnotify_verbose != 0 )
874
    {
875
      libcnotify_printf(
876
       "%s: SSAT sector offset\t\t\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
877
       function,
878
       ssat_sector_offset,
879
       ssat_sector_offset );
880
    }
881
#endif
882
29.5k
    read_count = libbfio_handle_read_buffer_at_offset(
883
29.5k
            file_io_handle,
884
29.5k
            ssat_sector,
885
29.5k
            io_handle->sector_size,
886
29.5k
            ssat_sector_offset,
887
29.5k
            error );
888
889
29.5k
    if( read_count != (ssize_t) io_handle->sector_size )
890
885
    {
891
885
      libcerror_error_set(
892
885
       error,
893
885
       LIBCERROR_ERROR_DOMAIN_IO,
894
885
       LIBCERROR_IO_ERROR_READ_FAILED,
895
885
       "%s: unable to read SSAT sector at offset: %" PRIi64 " (0x%08" PRIx64 ").",
896
885
       function,
897
885
       ssat_sector_offset,
898
885
       ssat_sector_offset );
899
900
885
      goto on_error;
901
885
    }
902
#if defined( HAVE_DEBUG_OUTPUT )
903
    if( libcnotify_verbose != 0 )
904
    {
905
      libcnotify_printf(
906
       "%s: SSAT sector:\n",
907
       function );
908
      libcnotify_print_data(
909
       ssat_sector,
910
       io_handle->sector_size,
911
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
912
    }
913
#endif
914
28.6k
    ssat_entry = ssat_sector;
915
916
28.6k
    for( ssat_sector_entry_index = 0;
917
944k
         (size_t) ssat_sector_entry_index < number_of_ssat_sector_entries;
918
915k
         ssat_sector_entry_index++ )
919
915k
    {
920
915k
      if( ( ssat_index < 0 )
921
915k
       || ( ssat_index >= ssat->number_of_sector_identifiers ) )
922
64
      {
923
64
        libcerror_error_set(
924
64
         error,
925
64
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
926
64
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
927
64
         "%s: invalid SSAT entry: %04d value out of bounds.",
928
64
         function,
929
64
         ssat_index );
930
931
64
        goto on_error;
932
64
      }
933
915k
      if( io_handle->byte_order == LIBOLECF_ENDIAN_LITTLE )
934
418k
      {
935
418k
        byte_stream_copy_to_uint32_little_endian(
936
418k
         ssat_entry,
937
418k
         ssat->sector_identifiers[ ssat_index ] );
938
418k
      }
939
497k
      else if( io_handle->byte_order == LIBOLECF_ENDIAN_BIG )
940
497k
      {
941
497k
        byte_stream_copy_to_uint32_big_endian(
942
497k
         ssat_entry,
943
497k
         ssat->sector_identifiers[ ssat_index ] );
944
497k
      }
945
#if defined( HAVE_DEBUG_OUTPUT )
946
      if( libcnotify_verbose != 0 )
947
      {
948
        libcnotify_printf(
949
         "%s: SSAT entry: %04d sector identifier\t: 0x%08" PRIx32 "\n",
950
         function,
951
         ssat_index,
952
         ssat->sector_identifiers[ ssat_index ] );
953
      }
954
#endif
955
915k
      ssat_entry += 4;
956
957
915k
      ssat_index++;
958
915k
    }
959
#if defined( HAVE_DEBUG_OUTPUT )
960
    if( libcnotify_verbose != 0 )
961
    {
962
      libcnotify_printf(
963
       "\n" );
964
    }
965
#endif
966
28.5k
#if SIZE_OF_INT <= 4
967
28.5k
    if( ssat_sector_identifier > (uint32_t) INT_MAX )
968
0
    {
969
0
      libcerror_error_set(
970
0
       error,
971
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
972
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
973
0
       "%s: invalid SSAT sector identifier: 0x%08" PRIx32 " value out of bounds.",
974
0
       function,
975
0
       ssat_sector_identifier );
976
977
0
      goto on_error;
978
0
    }
979
28.5k
#endif
980
28.5k
    if( libolecf_allocation_table_get_sector_identifier_by_index(
981
28.5k
         sat,
982
28.5k
         (int) ssat_sector_identifier,
983
28.5k
         &ssat_sector_identifier,
984
28.5k
         error ) != 1 )
985
38
    {
986
38
      libcerror_error_set(
987
38
       error,
988
38
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
989
38
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
990
38
       "%s: unable to retrieve sector identifier: %" PRIu32 " from SAT.",
991
38
       function,
992
38
       ssat_sector_identifier );
993
994
38
      goto on_error;
995
38
    }
996
28.5k
    ssat_sector_index++;
997
28.5k
  }
998
265
  memory_free(
999
265
   ssat_sector );
1000
1001
265
  return( 1 );
1002
1003
1.22k
on_error:
1004
1.22k
  if( ssat_sector != NULL )
1005
1.11k
  {
1006
1.11k
    memory_free(
1007
1.11k
     ssat_sector );
1008
1.11k
  }
1009
1.22k
  return( 1 );
1010
1.38k
}
1011
1012
/* Reads the directory entries
1013
 * This function requires that the SAT was read
1014
 * Returns 1 if successful or -1 on error
1015
 */
1016
int libolecf_io_handle_read_directory_entries(
1017
     libolecf_io_handle_t *io_handle,
1018
     libbfio_handle_t *file_io_handle,
1019
     libolecf_allocation_table_t *sat,
1020
     libcdata_list_t *directory_entry_list,
1021
     uint32_t root_directory_sector_identifier,
1022
     libcerror_error_t **error )
1023
1.48k
{
1024
1.48k
  libcdata_range_list_t *read_directory_sector_list = NULL;
1025
1.48k
  libolecf_directory_entry_t *directory_entry       = NULL;
1026
1.48k
  uint8_t *directory_entry_data                     = NULL;
1027
1.48k
  uint8_t *directory_sector                         = NULL;
1028
1.48k
  static char *function                             = "libolecf_io_handle_read_directory_entries";
1029
1.48k
  size_t number_of_directory_sector_entries         = 0;
1030
1.48k
  ssize_t read_count                                = 0;
1031
1.48k
  off64_t directory_sector_offset                   = 0;
1032
1.48k
  uint32_t directory_sector_identifier              = 0;
1033
1.48k
  int directory_entry_index                         = 0;
1034
1.48k
  int directory_sector_index                        = 0;
1035
1.48k
  int recursion_depth                               = 0;
1036
1.48k
  int result                                        = 0;
1037
1038
1.48k
  if( io_handle == NULL )
1039
0
  {
1040
0
    libcerror_error_set(
1041
0
     error,
1042
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1043
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1044
0
     "%s: invalid IO handle.",
1045
0
     function );
1046
1047
0
    return( -1 );
1048
0
  }
1049
1.48k
  if( ( io_handle->sector_size == 0 )
1050
1.48k
   || ( io_handle->sector_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
1051
1.48k
   || ( ( io_handle->sector_size % sizeof( olecf_directory_entry_t ) ) != 0 ) )
1052
163
  {
1053
163
    libcerror_error_set(
1054
163
     error,
1055
163
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1056
163
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1057
163
     "%s: invalid IO handle - sector size value out of bounds.",
1058
163
     function );
1059
1060
163
    return( -1 );
1061
163
  }
1062
1.32k
  if( sat == NULL )
1063
0
  {
1064
0
    libcerror_error_set(
1065
0
     error,
1066
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1067
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1068
0
     "%s: invalid SAT.",
1069
0
     function );
1070
1071
0
    return( -1 );
1072
0
  }
1073
1.32k
  if( directory_entry_list == NULL )
1074
0
  {
1075
0
    libcerror_error_set(
1076
0
     error,
1077
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1078
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1079
0
     "%s: invalid directory entry list.",
1080
0
     function );
1081
1082
0
    return( -1 );
1083
0
  }
1084
1.32k
  if( root_directory_sector_identifier == LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
1085
2
  {
1086
2
    libcerror_error_set(
1087
2
     error,
1088
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1089
2
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1090
2
     "%s: invalid root directory sector identifier.",
1091
2
     function );
1092
1093
2
    return( -1 );
1094
2
  }
1095
1.32k
  number_of_directory_sector_entries = io_handle->sector_size / sizeof( olecf_directory_entry_t );
1096
1097
1.32k
  directory_sector = (uint8_t *) memory_allocate(
1098
1.32k
                                  sizeof( uint8_t ) * io_handle->sector_size );
1099
1100
1.32k
  if( directory_sector == NULL )
1101
0
  {
1102
0
    libcerror_error_set(
1103
0
     error,
1104
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1105
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1106
0
     "%s: unable to create directory sector.",
1107
0
     function );
1108
1109
0
    goto on_error;
1110
0
  }
1111
1.32k
  if( libcdata_range_list_initialize(
1112
1.32k
       &read_directory_sector_list,
1113
1.32k
       error ) != 1 )
1114
0
  {
1115
0
    libcerror_error_set(
1116
0
     error,
1117
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1118
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1119
0
     "%s: unable to create read directory sector list.",
1120
0
     function );
1121
1122
0
    goto on_error;
1123
0
  }
1124
1.32k
  directory_sector_identifier = root_directory_sector_identifier;
1125
1126
56.4k
  while( ( directory_sector_identifier != LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
1127
56.4k
      && ( directory_sector_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED ) )
1128
56.1k
  {
1129
56.1k
    if( recursion_depth > LIBOLECF_MAXIMUM_DIRECTORY_ENTRIES_RECURSION_DEPTH )
1130
2
    {
1131
2
      libcerror_error_set(
1132
2
       error,
1133
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1134
2
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1135
2
       "%s: invalid recursion depth value out of bounds.",
1136
2
       function );
1137
1138
2
      goto on_error;
1139
2
    }
1140
56.1k
    recursion_depth++;
1141
1142
56.1k
    result = libcdata_range_list_range_is_present(
1143
56.1k
              read_directory_sector_list,
1144
56.1k
              (uint64_t) directory_sector_identifier,
1145
56.1k
              (uint64_t) 1,
1146
56.1k
              error );
1147
1148
56.1k
    if( result == -1 )
1149
0
    {
1150
0
      libcerror_error_set(
1151
0
       error,
1152
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1153
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1154
0
       "%s: unable to determine if directory sector is in range list.",
1155
0
       function );
1156
1157
0
      goto on_error;
1158
0
    }
1159
56.1k
    else if( result != 0 )
1160
509
    {
1161
509
      break;
1162
509
    }
1163
#if defined( HAVE_DEBUG_OUTPUT )
1164
    if( libcnotify_verbose != 0 )
1165
    {
1166
      libcnotify_printf(
1167
       "%s: directory sector identifier\t: 0x%08" PRIx32 "\n",
1168
       function,
1169
       directory_sector_identifier );
1170
    }
1171
#endif
1172
55.6k
    directory_sector_offset = ( directory_sector_identifier + 1 ) * io_handle->sector_size;
1173
1174
#if defined( HAVE_DEBUG_OUTPUT )
1175
    if( libcnotify_verbose != 0 )
1176
    {
1177
      libcnotify_printf(
1178
       "%s: directory sector offset\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
1179
       function,
1180
       directory_sector_offset,
1181
       directory_sector_offset );
1182
    }
1183
#endif
1184
55.6k
    read_count = libbfio_handle_read_buffer_at_offset(
1185
55.6k
            file_io_handle,
1186
55.6k
            directory_sector,
1187
55.6k
            io_handle->sector_size,
1188
55.6k
            directory_sector_offset,
1189
55.6k
            error );
1190
1191
55.6k
    if( read_count != (ssize_t) io_handle->sector_size )
1192
519
    {
1193
519
      libcerror_error_set(
1194
519
       error,
1195
519
       LIBCERROR_ERROR_DOMAIN_IO,
1196
519
       LIBCERROR_IO_ERROR_READ_FAILED,
1197
519
       "%s: unable to read directory sector at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1198
519
       function,
1199
519
       directory_sector_offset,
1200
519
       directory_sector_offset );
1201
1202
519
      goto on_error;
1203
519
    }
1204
#if defined( HAVE_DEBUG_OUTPUT )
1205
    if( libcnotify_verbose != 0 )
1206
    {
1207
      libcnotify_printf(
1208
       "%s: directory sector:\n",
1209
       function );
1210
      libcnotify_print_data(
1211
       directory_sector,
1212
       io_handle->sector_size,
1213
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1214
    }
1215
#endif
1216
55.1k
    directory_entry_data = directory_sector;
1217
1218
55.1k
    for( directory_sector_index = 0;
1219
255k
         (size_t) directory_sector_index < number_of_directory_sector_entries;
1220
200k
         directory_sector_index++ )
1221
200k
    {
1222
200k
      if( libolecf_directory_entry_initialize(
1223
200k
           &directory_entry,
1224
200k
           error ) != 1 )
1225
0
      {
1226
0
        libcerror_error_set(
1227
0
         error,
1228
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1229
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1230
0
         "%s: unable to create directory entry: %d.",
1231
0
         function,
1232
0
         directory_sector_index );
1233
1234
0
        goto on_error;
1235
0
      }
1236
200k
      result = libolecf_directory_entry_read_data(
1237
200k
                directory_entry,
1238
200k
                directory_entry_index,
1239
200k
                directory_entry_data,
1240
200k
                sizeof( olecf_directory_entry_t ),
1241
200k
                io_handle->byte_order,
1242
200k
                error );
1243
1244
200k
      if( result == -1 )
1245
55
      {
1246
55
        libcerror_error_set(
1247
55
         error,
1248
55
         LIBCERROR_ERROR_DOMAIN_IO,
1249
55
         LIBCERROR_IO_ERROR_READ_FAILED,
1250
55
         "%s: unable to read directory entry: %d.",
1251
55
         function,
1252
55
         directory_sector_index );
1253
1254
55
        goto on_error;
1255
55
      }
1256
200k
      if( directory_entry->type == LIBOLECF_ITEM_TYPE_EMPTY )
1257
23.8k
      {
1258
#if defined( HAVE_DEBUG_OUTPUT )
1259
        if( libcnotify_verbose != 0 )
1260
        {
1261
          libcnotify_printf(
1262
           "%s: directory sector entry: %d is empty (type is empty).\n",
1263
           function,
1264
           directory_sector_index );
1265
        }
1266
#endif
1267
23.8k
        if( libolecf_directory_entry_free(
1268
23.8k
             &directory_entry,
1269
23.8k
             error ) != 1 )
1270
0
        {
1271
0
          libcerror_error_set(
1272
0
           error,
1273
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1274
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1275
0
           "%s: unable to free directory entry.",
1276
0
           function );
1277
1278
0
          goto on_error;
1279
0
        }
1280
23.8k
      }
1281
176k
      else
1282
176k
      {
1283
176k
        if( libcdata_list_append_value(
1284
176k
             directory_entry_list,
1285
176k
             (intptr_t *) directory_entry,
1286
176k
             error ) != 1 )
1287
0
        {
1288
0
          libcerror_error_set(
1289
0
           error,
1290
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1291
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1292
0
           "%s: unable to append directory entry.",
1293
0
           function );
1294
1295
0
          goto on_error;
1296
0
        }
1297
176k
        directory_entry = NULL;
1298
176k
      }
1299
200k
      directory_entry_index++;
1300
1301
200k
      directory_entry_data += sizeof( olecf_directory_entry_t );
1302
200k
    }
1303
#if defined( HAVE_DEBUG_OUTPUT )
1304
    if( libcnotify_verbose != 0 )
1305
    {
1306
      libcnotify_printf(
1307
       "\n" );
1308
    }
1309
#endif
1310
55.0k
    result = libcdata_range_list_insert_range(
1311
55.0k
              read_directory_sector_list,
1312
55.0k
              (uint64_t) directory_sector_identifier,
1313
55.0k
              (uint64_t) 1,
1314
55.0k
              NULL,
1315
55.0k
              NULL,
1316
55.0k
              NULL,
1317
55.0k
              error );
1318
1319
55.0k
    if( result == -1 )
1320
0
    {
1321
0
      libcerror_error_set(
1322
0
       error,
1323
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1324
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1325
0
       "%s: unable to insert directory sector into range list.",
1326
0
       function );
1327
1328
0
      goto on_error;
1329
0
    }
1330
55.0k
#if SIZE_OF_INT <= 4
1331
55.0k
    if( directory_sector_identifier > (uint32_t) INT_MAX )
1332
0
    {
1333
0
      libcerror_error_set(
1334
0
       error,
1335
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1336
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1337
0
       "%s: invalid directory sector identifier: 0x%08" PRIx32 " value out of bounds.",
1338
0
       function,
1339
0
       directory_sector_identifier );
1340
1341
0
      goto on_error;
1342
0
    }
1343
55.0k
#endif
1344
55.0k
    if( libolecf_allocation_table_get_sector_identifier_by_index(
1345
55.0k
         sat,
1346
55.0k
         (int) directory_sector_identifier,
1347
55.0k
         &directory_sector_identifier,
1348
55.0k
         error ) != 1 )
1349
7
    {
1350
7
      libcerror_error_set(
1351
7
       error,
1352
7
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1353
7
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1354
7
       "%s: unable to retrieve sector identifier: %" PRIu32 " from SAT.",
1355
7
       function,
1356
7
       directory_sector_identifier );
1357
1358
7
      goto on_error;
1359
7
    }
1360
55.0k
  }
1361
739
  if( libcdata_range_list_free(
1362
739
       &read_directory_sector_list,
1363
739
       NULL,
1364
739
       error ) != 1 )
1365
0
  {
1366
0
    libcerror_error_set(
1367
0
     error,
1368
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1369
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1370
0
     "%s: unable to free read directory sector list.",
1371
0
     function );
1372
1373
0
    goto on_error;
1374
0
  }
1375
739
  memory_free(
1376
739
   directory_sector );
1377
1378
739
  directory_sector = NULL;
1379
1380
739
  return( 1 );
1381
1382
583
on_error:
1383
583
  if( directory_entry != NULL )
1384
55
  {
1385
55
    libolecf_directory_entry_free(
1386
55
     &directory_entry,
1387
55
     NULL );
1388
55
  }
1389
583
  if( read_directory_sector_list != NULL )
1390
583
  {
1391
583
    libcdata_range_list_free(
1392
583
     &read_directory_sector_list,
1393
583
     NULL,
1394
583
     NULL );
1395
583
  }
1396
583
  if( directory_sector != NULL )
1397
583
  {
1398
583
    memory_free(
1399
583
     directory_sector );
1400
583
  }
1401
583
  libcdata_list_empty(
1402
583
   directory_entry_list,
1403
583
         (int (*)(intptr_t **, libcerror_error_t **)) &libolecf_directory_entry_free,
1404
583
   NULL );
1405
1406
583
  return( -1 );
1407
739
}
1408
1409
/* Reads a buffer from the stream
1410
 * This function requires that the SAT and SSAT were read
1411
 * Returns 1 if successful or -1 on error
1412
 */
1413
ssize_t libolecf_io_handle_read_stream(
1414
         libolecf_io_handle_t *io_handle,
1415
         libbfio_handle_t *file_io_handle,
1416
         libolecf_allocation_table_t *sat,
1417
         libolecf_allocation_table_t *ssat,
1418
         libolecf_directory_entry_t *directory_entry,
1419
         off64_t *offset,
1420
         uint8_t *buffer,
1421
         size_t size,
1422
         libcerror_error_t **error )
1423
0
{
1424
0
  libolecf_allocation_table_t *allocation_table  = NULL;
1425
0
  static char *function                          = "libolecf_io_handle_read_stream";
1426
0
  off64_t read_offset                            = 0;
1427
0
  off64_t safe_offset                            = 0;
1428
0
  off64_t sector_boundary_offset                 = 0;
1429
0
  size_t buffer_offset                           = 0;
1430
0
  size_t read_size                               = 0;
1431
0
  size_t sector_size                             = 0;
1432
0
  ssize_t read_count                             = 0;
1433
0
  uint32_t sector_identifier                     = 0;
1434
0
  uint32_t short_sector_stream_sector_identifier = 0;
1435
0
  int sector_identifier_index                    = 0;
1436
0
  int sector_identifier_iterator                 = 0;
1437
1438
0
  if( io_handle == NULL )
1439
0
  {
1440
0
    libcerror_error_set(
1441
0
     error,
1442
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1443
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1444
0
     "%s: invalid IO handle.",
1445
0
     function );
1446
1447
0
    return( -1 );
1448
0
  }
1449
0
  if( directory_entry == NULL )
1450
0
  {
1451
0
    libcerror_error_set(
1452
0
     error,
1453
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1454
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1455
0
     "%s: invalid directory entry.",
1456
0
     function );
1457
1458
0
    return( -1 );
1459
0
  }
1460
0
  if( offset == NULL )
1461
0
  {
1462
0
    libcerror_error_set(
1463
0
     error,
1464
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1465
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1466
0
     "%s: invalid offset.",
1467
0
     function );
1468
1469
0
    return( -1 );
1470
0
  }
1471
0
  safe_offset = *offset;
1472
1473
0
  if( safe_offset < 0 )
1474
0
  {
1475
0
    libcerror_error_set(
1476
0
     error,
1477
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1478
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1479
0
     "%s: invalid offset value out of bounds.",
1480
0
     function );
1481
1482
0
    return( -1 );
1483
0
  }
1484
/* TODO offset upper boundary check ? */
1485
0
  if( buffer == NULL )
1486
0
  {
1487
0
    libcerror_error_set(
1488
0
     error,
1489
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1490
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1491
0
     "%s: invalid buffer.",
1492
0
     function );
1493
1494
0
    return( -1 );
1495
0
  }
1496
0
  if( size > (size_t) SSIZE_MAX )
1497
0
  {
1498
0
    libcerror_error_set(
1499
0
     error,
1500
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1501
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1502
0
     "%s: invalid size value exceeds maximum.",
1503
0
     function );
1504
1505
0
    return( -1 );
1506
0
  }
1507
0
  if( directory_entry->size < io_handle->sector_stream_minimum_data_size )
1508
0
  {
1509
0
    if( ssat == NULL )
1510
0
    {
1511
0
      libcerror_error_set(
1512
0
       error,
1513
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1514
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1515
0
       "%s: invalid SSAT.",
1516
0
       function );
1517
1518
0
      return( -1 );
1519
0
    }
1520
0
    allocation_table = ssat;
1521
0
    sector_size      = io_handle->short_sector_size;
1522
0
  }
1523
0
  else
1524
0
  {
1525
0
    if( sat == NULL )
1526
0
    {
1527
0
      libcerror_error_set(
1528
0
       error,
1529
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1530
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1531
0
       "%s: invalid SAT.",
1532
0
       function );
1533
1534
0
      return( -1 );
1535
0
    }
1536
0
    allocation_table = sat;
1537
0
    sector_size      = io_handle->sector_size;
1538
0
  }
1539
0
  sector_identifier_index = (int) ( safe_offset / sector_size );
1540
1541
0
  if( ( sector_identifier_index < 0 )
1542
0
   || ( sector_identifier_index >= allocation_table->number_of_sector_identifiers ) )
1543
0
  {
1544
0
    libcerror_error_set(
1545
0
     error,
1546
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1547
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1548
0
     "%s: invalid sector identifier index value out of bounds.",
1549
0
     function );
1550
1551
0
    return( -1 );
1552
0
  }
1553
0
  sector_identifier = directory_entry->sector_identifier;
1554
1555
0
  for( sector_identifier_iterator = sector_identifier_index;
1556
0
       sector_identifier_iterator > 0;
1557
0
       sector_identifier_iterator-- )
1558
0
  {
1559
0
    if( sector_identifier == LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
1560
0
    {
1561
0
      libcerror_error_set(
1562
0
       error,
1563
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1564
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1565
0
       "%s: invalid sector identifier.",
1566
0
       function );
1567
1568
0
      return( -1 );
1569
0
    }
1570
0
#if SIZE_OF_INT <= 4
1571
0
    if( sector_identifier > (uint32_t) INT_MAX )
1572
0
    {
1573
0
      libcerror_error_set(
1574
0
       error,
1575
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1576
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1577
0
       "%s: invalid sector identifier: 0x%08" PRIx32 " value out of bounds.",
1578
0
       function,
1579
0
       sector_identifier );
1580
1581
0
      return( -1 );
1582
0
    }
1583
0
#endif
1584
0
    if( libolecf_allocation_table_get_sector_identifier_by_index(
1585
0
         allocation_table,
1586
0
         (int) sector_identifier,
1587
0
         &sector_identifier,
1588
0
         error ) != 1 )
1589
0
    {
1590
0
      libcerror_error_set(
1591
0
       error,
1592
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1593
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1594
0
       "%s: unable to retrieve sector identifier: %" PRIu32 " from allocation table.",
1595
0
       function,
1596
0
       sector_identifier );
1597
1598
0
      return( -1 );
1599
0
    }
1600
0
  }
1601
0
  while( size > 0 )
1602
0
  {
1603
0
    if( sector_identifier == LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
1604
0
    {
1605
0
      libcerror_error_set(
1606
0
       error,
1607
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1608
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1609
0
       "%s: invalid sector identifier.",
1610
0
       function );
1611
1612
0
      return( -1 );
1613
0
    }
1614
0
    sector_boundary_offset = (off64_t) ( sector_identifier_index * sector_size );
1615
1616
    /* Determine start offset and read size
1617
     */
1618
0
    if( directory_entry->size < io_handle->sector_stream_minimum_data_size )
1619
0
    {
1620
0
      read_offset = sector_identifier * sector_size;
1621
1622
0
      short_sector_stream_sector_identifier = io_handle->short_sector_stream_start_sector_identifier;
1623
1624
0
      while( read_offset >= (off64_t) io_handle->sector_size )
1625
0
      {
1626
0
#if SIZE_OF_INT <= 4
1627
0
        if( short_sector_stream_sector_identifier > (uint32_t) INT_MAX )
1628
0
        {
1629
0
          libcerror_error_set(
1630
0
           error,
1631
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1632
0
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1633
0
           "%s: invalid short sector stream sector identifier: 0x%08" PRIx32 " value out of bounds.",
1634
0
           function,
1635
0
           short_sector_stream_sector_identifier );
1636
1637
0
          return( -1 );
1638
0
        }
1639
0
#endif
1640
0
        if( libolecf_allocation_table_get_sector_identifier_by_index(
1641
0
             sat,
1642
0
             (int) short_sector_stream_sector_identifier,
1643
0
             &short_sector_stream_sector_identifier,
1644
0
             error ) != 1 )
1645
0
        {
1646
0
          libcerror_error_set(
1647
0
           error,
1648
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1649
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1650
0
           "%s: unable to retrieve sector identifier: %" PRIu32 " from SAT.",
1651
0
           function,
1652
0
           short_sector_stream_sector_identifier );
1653
1654
0
          return( -1 );
1655
0
        }
1656
0
        read_offset -= io_handle->sector_size;
1657
0
      }
1658
0
      read_offset += ( short_sector_stream_sector_identifier + 1 ) * io_handle->sector_size;
1659
0
    }
1660
0
    else
1661
0
    {
1662
0
      read_offset = ( sector_identifier + 1 ) * sector_size;
1663
0
    }
1664
0
    read_size = sector_size;
1665
1666
0
    if( safe_offset > sector_boundary_offset )
1667
0
    {
1668
0
      read_offset += safe_offset - sector_boundary_offset;
1669
0
      read_size   -= (size_t) ( safe_offset - sector_boundary_offset );
1670
0
    }
1671
0
    if( read_size > size )
1672
0
    {
1673
0
      read_size = size;
1674
0
    }
1675
    /* Read sector data into the buffer
1676
     */
1677
0
    read_count = libbfio_handle_read_buffer_at_offset(
1678
0
            file_io_handle,
1679
0
            &( buffer[ buffer_offset ] ),
1680
0
            read_size,
1681
0
            read_offset,
1682
0
            error );
1683
1684
0
    if( read_count != (ssize_t) read_size )
1685
0
    {
1686
0
      libcerror_error_set(
1687
0
       error,
1688
0
       LIBCERROR_ERROR_DOMAIN_IO,
1689
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1690
0
       "%s: unable to read sector: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1691
0
       function,
1692
0
       sector_identifier,
1693
0
       read_offset,
1694
0
       read_offset );
1695
1696
0
      return( -1 );
1697
0
    }
1698
0
    buffer_offset += read_size;
1699
0
    safe_offset   += read_size;
1700
0
    size          -= read_size;
1701
1702
0
#if SIZE_OF_INT <= 4
1703
0
    if( sector_identifier > (uint32_t) INT_MAX )
1704
0
    {
1705
0
      libcerror_error_set(
1706
0
       error,
1707
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1708
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1709
0
       "%s: invalid sector identifier: 0x%08" PRIx32 " value out of bounds.",
1710
0
       function,
1711
0
       sector_identifier );
1712
1713
0
      return( -1 );
1714
0
    }
1715
0
#endif
1716
0
    if( libolecf_allocation_table_get_sector_identifier_by_index(
1717
0
         allocation_table,
1718
0
         (int) sector_identifier,
1719
0
         &sector_identifier,
1720
0
         error ) != 1 )
1721
0
    {
1722
0
      libcerror_error_set(
1723
0
       error,
1724
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1725
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1726
0
       "%s: unable to retrieve sector identifier: %" PRIu32 " from allocation table.",
1727
0
       function,
1728
0
       sector_identifier );
1729
1730
0
      return( -1 );
1731
0
    }
1732
0
    sector_identifier_index++;
1733
0
  }
1734
0
  *offset = safe_offset;
1735
1736
0
  return( (ssize_t) buffer_offset );
1737
0
}
1738