Coverage Report

Created: 2024-06-12 07:07

/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.81k
{
55
1.81k
  static char *function = "libolecf_io_handle_initialize";
56
57
1.81k
  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.81k
  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.81k
  *io_handle = memory_allocate_structure(
80
1.81k
                libolecf_io_handle_t );
81
82
1.81k
  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.81k
  if( memory_set(
94
1.81k
       *io_handle,
95
1.81k
       0,
96
1.81k
       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.81k
  ( *io_handle )->ascii_codepage = LIBOLECF_CODEPAGE_WINDOWS_1252;
113
114
1.81k
  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.81k
}
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.81k
{
134
1.81k
  static char *function = "libolecf_io_handle_free";
135
1.81k
  int result            = 1;
136
137
1.81k
  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.81k
  if( *io_handle != NULL )
149
1.81k
  {
150
1.81k
    memory_free(
151
1.81k
     *io_handle );
152
153
1.81k
    *io_handle = NULL;
154
1.81k
  }
155
1.81k
  return( result );
156
1.81k
}
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
144
{
165
144
  static char *function = "libolecf_io_handle_clear";
166
167
144
  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
144
  if( memory_set(
179
144
       io_handle,
180
144
       0,
181
144
       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
144
  io_handle->ascii_codepage = LIBOLECF_CODEPAGE_WINDOWS_1252;
193
194
144
  return( 1 );
195
144
}
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.54k
{
209
1.54k
  uint8_t *msat_sector                 = NULL;
210
1.54k
  uint8_t *msat_entry                  = NULL;
211
1.54k
  static char *function                = "libolecf_io_handle_read_msat";
212
1.54k
  off64_t msat_sector_offset           = 0;
213
1.54k
  size_t number_of_msat_sector_entries = 0;
214
1.54k
  ssize_t read_count                   = 0;
215
1.54k
  int number_of_msat_entries           = 0;
216
1.54k
  int msat_index                       = 109;
217
1.54k
  int msat_sector_index                = 0;
218
1.54k
  int recursion_depth                  = 0;
219
220
1.54k
  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.54k
  if( ( io_handle->sector_size == 0 )
232
1.54k
   || ( 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.54k
  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.54k
  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.54k
  if( ( msat_sector_identifier == LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
268
1.54k
   && ( number_of_msat_sectors == 0 ) )
269
240
  {
270
240
    return( 1 );
271
240
  }
272
1.30k
  if( msat_sector_identifier == LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
273
79
  {
274
79
    libcerror_error_set(
275
79
     error,
276
79
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
277
79
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
278
79
     "%s: invalid MSAT sector identifier.",
279
79
     function );
280
281
79
    return( -1 );
282
79
  }
283
1.22k
  if( number_of_msat_sectors == 0 )
284
342
  {
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
342
    number_of_msat_sectors = 1;
294
342
  }
295
1.22k
  number_of_msat_sector_entries = io_handle->sector_size / 4;
296
297
1.22k
  if( number_of_msat_sector_entries == 0 )
298
2
  {
299
2
    libcerror_error_set(
300
2
     error,
301
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
302
2
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
303
2
     "%s: invalid number of MSAT sector entries value out of bounds.",
304
2
     function );
305
306
2
    goto on_error;
307
2
  }
308
  /* The last MSAT entry is reserved for the next MSAT sector identifier.
309
   */
310
1.22k
  number_of_msat_sector_entries -= 1;
311
312
1.22k
  number_of_msat_entries = 109 + ( number_of_msat_sectors * number_of_msat_sector_entries );
313
314
1.22k
  if( msat->number_of_sector_identifiers < number_of_msat_entries )
315
555
  {
316
555
    if( libolecf_allocation_table_resize(
317
555
         msat,
318
555
         number_of_msat_entries,
319
555
         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
555
  }
331
1.22k
  msat_sector = (uint8_t *) memory_allocate(
332
1.22k
                             sizeof( uint8_t ) * io_handle->sector_size );
333
334
1.22k
  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.3k
  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
12
    {
349
12
      libcerror_error_set(
350
12
       error,
351
12
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
352
12
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
353
12
       "%s: invalid recursion depth value out of bounds.",
354
12
       function );
355
356
12
      goto on_error;
357
12
    }
358
15.3k
    recursion_depth++;
359
360
15.3k
    if( msat_index >= msat->number_of_sector_identifiers )
361
1.12k
    {
362
1.12k
      break;
363
1.12k
    }
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
40
    {
385
40
      libcerror_error_set(
386
40
       error,
387
40
       LIBCERROR_ERROR_DOMAIN_IO,
388
40
       LIBCERROR_IO_ERROR_READ_FAILED,
389
40
       "%s: unable to read MSAT sector at offset: %" PRIi64 " (0x%08" PRIx64 ").",
390
40
       function,
391
40
       msat_sector_offset,
392
40
       msat_sector_offset );
393
394
40
      goto on_error;
395
40
    }
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
8.44M
         (size_t) msat_sector_index < number_of_msat_sector_entries;
412
8.43M
         msat_sector_index++ )
413
8.43M
    {
414
8.43M
      if( ( msat_index < 0 )
415
8.43M
       || ( 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
8.43M
      if( io_handle->byte_order == LIBOLECF_ENDIAN_LITTLE )
428
7.75M
      {
429
7.75M
        byte_stream_copy_to_uint32_little_endian(
430
7.75M
         msat_entry,
431
7.75M
         msat->sector_identifiers[ msat_index ] );
432
7.75M
      }
433
673k
      else if( io_handle->byte_order == LIBOLECF_ENDIAN_BIG )
434
673k
      {
435
673k
        byte_stream_copy_to_uint32_big_endian(
436
673k
         msat_entry,
437
673k
         msat->sector_identifiers[ msat_index ] );
438
673k
      }
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
8.43M
      msat_entry += 4;
450
451
8.43M
      msat_index++;
452
8.43M
    }
453
14.1k
    if( io_handle->byte_order == LIBOLECF_ENDIAN_LITTLE )
454
10.0k
    {
455
10.0k
      byte_stream_copy_to_uint32_little_endian(
456
10.0k
       msat_entry,
457
10.0k
       msat_sector_identifier );
458
10.0k
    }
459
4.09k
    else if( io_handle->byte_order == LIBOLECF_ENDIAN_BIG )
460
4.09k
    {
461
4.09k
      byte_stream_copy_to_uint32_big_endian(
462
4.09k
       msat_entry,
463
4.09k
       msat_sector_identifier );
464
4.09k
    }
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.16k
  memory_free(
478
1.16k
   msat_sector );
479
480
1.16k
  return( 1 );
481
482
62
on_error:
483
62
  if( msat_sector != NULL )
484
58
  {
485
58
    memory_free(
486
58
     msat_sector );
487
58
  }
488
62
  return( -1 );
489
490
1.22k
}
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.40k
{
504
1.40k
  uint8_t *sat_sector                 = NULL;
505
1.40k
  uint8_t *sat_entry                  = NULL;
506
1.40k
  static char *function               = "libolecf_io_handle_read_sat";
507
1.40k
  off64_t sat_sector_offset           = 0;
508
1.40k
  size_t number_of_sat_sector_entries = 0;
509
1.40k
  ssize_t read_count                  = 0;
510
1.40k
  int number_of_sat_entries           = 0;
511
1.40k
  int msat_index                      = 0;
512
1.40k
  int sat_index                       = 0;
513
1.40k
  int sat_sector_index                = 0;
514
515
1.40k
  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.40k
  if( ( io_handle->sector_size == 0 )
527
1.40k
   || ( 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.40k
  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.40k
  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.40k
  number_of_sat_sector_entries = io_handle->sector_size / 4;
561
1.40k
  number_of_sat_entries        = number_of_sat_sectors * number_of_sat_sector_entries;
562
563
1.40k
  if( sat->number_of_sector_identifiers < number_of_sat_entries )
564
1.29k
  {
565
1.29k
    if( libolecf_allocation_table_resize(
566
1.29k
         sat,
567
1.29k
         number_of_sat_entries,
568
1.29k
         error ) != 1 )
569
26
    {
570
26
      libcerror_error_set(
571
26
       error,
572
26
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
573
26
       LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
574
26
       "%s: unable to resize SAT.",
575
26
       function );
576
577
26
      goto on_error;
578
26
    }
579
1.29k
  }
580
1.38k
  sat_sector = (uint8_t *) memory_allocate(
581
1.38k
                            sizeof( uint8_t ) * io_handle->sector_size );
582
583
1.38k
  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.38k
  for( msat_index = 0;
595
26.8k
       msat_index < msat->number_of_sector_identifiers;
596
25.5k
       msat_index++ )
597
26.8k
  {
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
26.8k
    if( msat->sector_identifiers[ msat_index ] == LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
611
15.7k
    {
612
#if defined( HAVE_DEBUG_OUTPUT )
613
      if( libcnotify_verbose != 0 )
614
      {
615
        libcnotify_printf(
616
         "\n" );
617
      }
618
#endif
619
15.7k
      continue;
620
15.7k
    }
621
11.1k
    if( sat_index >= sat->number_of_sector_identifiers )
622
247
    {
623
247
      break;
624
247
    }
625
10.8k
    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
10.8k
    read_count = libbfio_handle_read_buffer_at_offset(
638
10.8k
            file_io_handle,
639
10.8k
            sat_sector,
640
10.8k
            io_handle->sector_size,
641
10.8k
            sat_sector_offset,
642
10.8k
            error );
643
644
10.8k
    if( read_count != (ssize_t) io_handle->sector_size )
645
1.12k
    {
646
1.12k
      libcerror_error_set(
647
1.12k
       error,
648
1.12k
       LIBCERROR_ERROR_DOMAIN_IO,
649
1.12k
       LIBCERROR_IO_ERROR_READ_FAILED,
650
1.12k
       "%s: unable to read SAT sector at offset: %" PRIi64 " (0x%08" PRIx64 ").",
651
1.12k
       function,
652
1.12k
       sat_sector_offset,
653
1.12k
       sat_sector_offset );
654
655
1.12k
      goto on_error;
656
1.12k
    }
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
9.76k
    sat_entry = sat_sector;
670
671
9.76k
    for( sat_sector_index = 0;
672
417k
         (size_t) sat_sector_index < number_of_sat_sector_entries;
673
407k
         sat_sector_index++ )
674
407k
    {
675
407k
      if( io_handle->byte_order == LIBOLECF_ENDIAN_LITTLE )
676
329k
      {
677
329k
        byte_stream_copy_to_uint32_little_endian(
678
329k
         sat_entry,
679
329k
         sat->sector_identifiers[ sat_index ] );
680
329k
      }
681
77.7k
      else if( io_handle->byte_order == LIBOLECF_ENDIAN_BIG )
682
77.7k
      {
683
77.7k
        byte_stream_copy_to_uint32_big_endian(
684
77.7k
         sat_entry,
685
77.7k
         sat->sector_identifiers[ sat_index ] );
686
77.7k
      }
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
407k
      sat_entry += 4;
698
699
407k
      sat_index++;
700
407k
    }
701
#if defined( HAVE_DEBUG_OUTPUT )
702
    if( libcnotify_verbose != 0 )
703
    {
704
      libcnotify_printf(
705
       "\n" );
706
    }
707
#endif
708
9.76k
  }
709
253
  memory_free(
710
253
   sat_sector );
711
712
253
  return( 1 );
713
714
1.15k
on_error:
715
1.15k
  if( sat_sector != NULL )
716
1.12k
  {
717
1.12k
    memory_free(
718
1.12k
     sat_sector );
719
1.12k
  }
720
1.15k
  return( 1 );
721
1.38k
}
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.40k
{
736
1.40k
  uint8_t *ssat_sector                 = NULL;
737
1.40k
  uint8_t *ssat_entry                  = NULL;
738
1.40k
  static char *function                = "libolecf_io_handle_read_ssat";
739
1.40k
  off64_t ssat_sector_offset           = 0;
740
1.40k
  size_t number_of_ssat_sector_entries = 0;
741
1.40k
  ssize_t read_count                   = 0;
742
1.40k
  uint32_t ssat_sector_index           = 0;
743
1.40k
  int number_of_ssat_entries           = 0;
744
1.40k
  int recursion_depth                  = 0;
745
1.40k
  int ssat_index                       = 0;
746
1.40k
  int ssat_sector_entry_index          = 0;
747
748
1.40k
  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.40k
  if( ( io_handle->sector_size == 0 )
760
1.40k
   || ( 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.40k
  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.40k
  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.40k
  number_of_ssat_sector_entries = io_handle->sector_size / 4;
794
1.40k
  number_of_ssat_entries        = number_of_ssat_sectors * number_of_ssat_sector_entries;
795
796
1.40k
  if( ssat->number_of_sector_identifiers < number_of_ssat_entries )
797
914
  {
798
914
    if( libolecf_allocation_table_resize(
799
914
         ssat,
800
914
         number_of_ssat_entries,
801
914
         error ) != 1 )
802
105
    {
803
105
      libcerror_error_set(
804
105
       error,
805
105
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
806
105
       LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
807
105
       "%s: unable to resize SSAT.",
808
105
       function );
809
810
105
      goto on_error;
811
105
    }
812
914
  }
813
1.30k
  ssat_sector = (uint8_t *) memory_allocate(
814
1.30k
                             sizeof( uint8_t ) * io_handle->sector_size );
815
816
1.30k
  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.8k
  while( ssat_sector_identifier != LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
828
42.8k
  {
829
42.8k
    if( recursion_depth > LIBOLECF_MAXIMUM_ALLOCATION_TABLE_RECURSION_DEPTH )
830
120
    {
831
120
      libcerror_error_set(
832
120
       error,
833
120
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
834
120
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
835
120
       "%s: invalid recursion depth value out of bounds.",
836
120
       function );
837
838
120
      goto on_error;
839
120
    }
840
42.6k
    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.6k
    if( ssat_sector_index >= number_of_ssat_sectors )
852
276
    {
853
276
      break;
854
276
    }
855
    /* Skip empty sector identifiers
856
     */
857
42.4k
    if( ssat_sector_identifier == LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
858
11.8k
    {
859
#if defined( HAVE_DEBUG_OUTPUT )
860
      if( libcnotify_verbose != 0 )
861
      {
862
        libcnotify_printf(
863
         "\n" );
864
      }
865
#endif
866
11.8k
      ssat_sector_index++;
867
868
11.8k
      continue;
869
11.8k
    }
870
30.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
30.5k
    read_count = libbfio_handle_read_buffer_at_offset(
883
30.5k
            file_io_handle,
884
30.5k
            ssat_sector,
885
30.5k
            io_handle->sector_size,
886
30.5k
            ssat_sector_offset,
887
30.5k
            error );
888
889
30.5k
    if( read_count != (ssize_t) io_handle->sector_size )
890
784
    {
891
784
      libcerror_error_set(
892
784
       error,
893
784
       LIBCERROR_ERROR_DOMAIN_IO,
894
784
       LIBCERROR_IO_ERROR_READ_FAILED,
895
784
       "%s: unable to read SSAT sector at offset: %" PRIi64 " (0x%08" PRIx64 ").",
896
784
       function,
897
784
       ssat_sector_offset,
898
784
       ssat_sector_offset );
899
900
784
      goto on_error;
901
784
    }
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
29.7k
    ssat_entry = ssat_sector;
915
916
29.7k
    for( ssat_sector_entry_index = 0;
917
1.07M
         (size_t) ssat_sector_entry_index < number_of_ssat_sector_entries;
918
1.04M
         ssat_sector_entry_index++ )
919
1.04M
    {
920
1.04M
      if( ( ssat_index < 0 )
921
1.04M
       || ( ssat_index >= ssat->number_of_sector_identifiers ) )
922
60
      {
923
60
        libcerror_error_set(
924
60
         error,
925
60
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
926
60
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
927
60
         "%s: invalid SSAT entry: %04d value out of bounds.",
928
60
         function,
929
60
         ssat_index );
930
931
60
        goto on_error;
932
60
      }
933
1.04M
      if( io_handle->byte_order == LIBOLECF_ENDIAN_LITTLE )
934
407k
      {
935
407k
        byte_stream_copy_to_uint32_little_endian(
936
407k
         ssat_entry,
937
407k
         ssat->sector_identifiers[ ssat_index ] );
938
407k
      }
939
637k
      else if( io_handle->byte_order == LIBOLECF_ENDIAN_BIG )
940
637k
      {
941
637k
        byte_stream_copy_to_uint32_big_endian(
942
637k
         ssat_entry,
943
637k
         ssat->sector_identifiers[ ssat_index ] );
944
637k
      }
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
1.04M
      ssat_entry += 4;
956
957
1.04M
      ssat_index++;
958
1.04M
    }
959
#if defined( HAVE_DEBUG_OUTPUT )
960
    if( libcnotify_verbose != 0 )
961
    {
962
      libcnotify_printf(
963
       "\n" );
964
    }
965
#endif
966
29.6k
#if SIZE_OF_INT <= 4
967
29.6k
    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
29.6k
#endif
980
29.6k
    if( libolecf_allocation_table_get_sector_identifier_by_index(
981
29.6k
         sat,
982
29.6k
         (int) ssat_sector_identifier,
983
29.6k
         &ssat_sector_identifier,
984
29.6k
         error ) != 1 )
985
29
    {
986
29
      libcerror_error_set(
987
29
       error,
988
29
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
989
29
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
990
29
       "%s: unable to retrieve sector identifier: %" PRIu32 " from SAT.",
991
29
       function,
992
29
       ssat_sector_identifier );
993
994
29
      goto on_error;
995
29
    }
996
29.6k
    ssat_sector_index++;
997
29.6k
  }
998
308
  memory_free(
999
308
   ssat_sector );
1000
1001
308
  return( 1 );
1002
1003
1.09k
on_error:
1004
1.09k
  if( ssat_sector != NULL )
1005
993
  {
1006
993
    memory_free(
1007
993
     ssat_sector );
1008
993
  }
1009
1.09k
  return( 1 );
1010
1.30k
}
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.40k
{
1024
1.40k
  libcdata_range_list_t *read_directory_sector_list = NULL;
1025
1.40k
  libolecf_directory_entry_t *directory_entry       = NULL;
1026
1.40k
  uint8_t *directory_entry_data                     = NULL;
1027
1.40k
  uint8_t *directory_sector                         = NULL;
1028
1.40k
  static char *function                             = "libolecf_io_handle_read_directory_entries";
1029
1.40k
  size_t number_of_directory_sector_entries         = 0;
1030
1.40k
  ssize_t read_count                                = 0;
1031
1.40k
  off64_t directory_sector_offset                   = 0;
1032
1.40k
  uint32_t directory_sector_identifier              = 0;
1033
1.40k
  int directory_entry_index                         = 0;
1034
1.40k
  int directory_sector_index                        = 0;
1035
1.40k
  int recursion_depth                               = 0;
1036
1.40k
  int result                                        = 0;
1037
1038
1.40k
  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.40k
  if( ( io_handle->sector_size == 0 )
1050
1.40k
   || ( io_handle->sector_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
1051
1.40k
   || ( ( io_handle->sector_size % sizeof( olecf_directory_entry_t ) ) != 0 ) )
1052
147
  {
1053
147
    libcerror_error_set(
1054
147
     error,
1055
147
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1056
147
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1057
147
     "%s: invalid IO handle - sector size value out of bounds.",
1058
147
     function );
1059
1060
147
    return( -1 );
1061
147
  }
1062
1.25k
  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.25k
  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.25k
  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.25k
  number_of_directory_sector_entries = io_handle->sector_size / sizeof( olecf_directory_entry_t );
1096
1097
1.25k
  directory_sector = (uint8_t *) memory_allocate(
1098
1.25k
                                  sizeof( uint8_t ) * io_handle->sector_size );
1099
1100
1.25k
  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.25k
  if( libcdata_range_list_initialize(
1112
1.25k
       &read_directory_sector_list,
1113
1.25k
       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.25k
  directory_sector_identifier = root_directory_sector_identifier;
1125
1126
30.9k
  while( ( directory_sector_identifier != LIBOLECF_SECTOR_IDENTIFIER_END_OF_CHAIN )
1127
30.9k
      && ( directory_sector_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED ) )
1128
30.7k
  {
1129
30.7k
    if( recursion_depth > LIBOLECF_MAXIMUM_DIRECTORY_ENTRIES_RECURSION_DEPTH )
1130
1
    {
1131
1
      libcerror_error_set(
1132
1
       error,
1133
1
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1134
1
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1135
1
       "%s: invalid recursion depth value out of bounds.",
1136
1
       function );
1137
1138
1
      goto on_error;
1139
1
    }
1140
30.7k
    recursion_depth++;
1141
1142
30.7k
    result = libcdata_range_list_range_is_present(
1143
30.7k
              read_directory_sector_list,
1144
30.7k
              (uint64_t) directory_sector_identifier,
1145
30.7k
              (uint64_t) 1,
1146
30.7k
              error );
1147
1148
30.7k
    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
30.7k
    else if( result != 0 )
1160
495
    {
1161
495
      break;
1162
495
    }
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
30.2k
    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
30.2k
    read_count = libbfio_handle_read_buffer_at_offset(
1185
30.2k
            file_io_handle,
1186
30.2k
            directory_sector,
1187
30.2k
            io_handle->sector_size,
1188
30.2k
            directory_sector_offset,
1189
30.2k
            error );
1190
1191
30.2k
    if( read_count != (ssize_t) io_handle->sector_size )
1192
501
    {
1193
501
      libcerror_error_set(
1194
501
       error,
1195
501
       LIBCERROR_ERROR_DOMAIN_IO,
1196
501
       LIBCERROR_IO_ERROR_READ_FAILED,
1197
501
       "%s: unable to read directory sector at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1198
501
       function,
1199
501
       directory_sector_offset,
1200
501
       directory_sector_offset );
1201
1202
501
      goto on_error;
1203
501
    }
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
29.7k
    directory_entry_data = directory_sector;
1217
1218
29.7k
    for( directory_sector_index = 0;
1219
130k
         (size_t) directory_sector_index < number_of_directory_sector_entries;
1220
100k
         directory_sector_index++ )
1221
100k
    {
1222
100k
      if( libolecf_directory_entry_initialize(
1223
100k
           &directory_entry,
1224
100k
           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
100k
      result = libolecf_directory_entry_read_data(
1237
100k
                directory_entry,
1238
100k
                directory_entry_index,
1239
100k
                directory_entry_data,
1240
100k
                sizeof( olecf_directory_entry_t ),
1241
100k
                io_handle->byte_order,
1242
100k
                error );
1243
1244
100k
      if( result == -1 )
1245
61
      {
1246
61
        libcerror_error_set(
1247
61
         error,
1248
61
         LIBCERROR_ERROR_DOMAIN_IO,
1249
61
         LIBCERROR_IO_ERROR_READ_FAILED,
1250
61
         "%s: unable to read directory entry: %d.",
1251
61
         function,
1252
61
         directory_sector_index );
1253
1254
61
        goto on_error;
1255
61
      }
1256
100k
      if( directory_entry->type == LIBOLECF_ITEM_TYPE_EMPTY )
1257
16.3k
      {
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
16.3k
        if( libolecf_directory_entry_free(
1268
16.3k
             &directory_entry,
1269
16.3k
             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
16.3k
      }
1281
84.2k
      else
1282
84.2k
      {
1283
84.2k
        if( libcdata_list_append_value(
1284
84.2k
             directory_entry_list,
1285
84.2k
             (intptr_t *) directory_entry,
1286
84.2k
             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
84.2k
        directory_entry = NULL;
1298
84.2k
      }
1299
100k
      directory_entry_index++;
1300
1301
100k
      directory_entry_data += sizeof( olecf_directory_entry_t );
1302
100k
    }
1303
#if defined( HAVE_DEBUG_OUTPUT )
1304
    if( libcnotify_verbose != 0 )
1305
    {
1306
      libcnotify_printf(
1307
       "\n" );
1308
    }
1309
#endif
1310
29.7k
    result = libcdata_range_list_insert_range(
1311
29.7k
              read_directory_sector_list,
1312
29.7k
              (uint64_t) directory_sector_identifier,
1313
29.7k
              (uint64_t) 1,
1314
29.7k
              NULL,
1315
29.7k
              NULL,
1316
29.7k
              NULL,
1317
29.7k
              error );
1318
1319
29.7k
    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
29.7k
#if SIZE_OF_INT <= 4
1331
29.7k
    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
29.7k
#endif
1344
29.7k
    if( libolecf_allocation_table_get_sector_identifier_by_index(
1345
29.7k
         sat,
1346
29.7k
         (int) directory_sector_identifier,
1347
29.7k
         &directory_sector_identifier,
1348
29.7k
         error ) != 1 )
1349
4
    {
1350
4
      libcerror_error_set(
1351
4
       error,
1352
4
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1353
4
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1354
4
       "%s: unable to retrieve sector identifier: %" PRIu32 " from SAT.",
1355
4
       function,
1356
4
       directory_sector_identifier );
1357
1358
4
      goto on_error;
1359
4
    }
1360
29.7k
  }
1361
690
  if( libcdata_range_list_free(
1362
690
       &read_directory_sector_list,
1363
690
       NULL,
1364
690
       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
690
  memory_free(
1376
690
   directory_sector );
1377
1378
690
  directory_sector = NULL;
1379
1380
690
  return( 1 );
1381
1382
567
on_error:
1383
567
  if( directory_entry != NULL )
1384
61
  {
1385
61
    libolecf_directory_entry_free(
1386
61
     &directory_entry,
1387
61
     NULL );
1388
61
  }
1389
567
  if( read_directory_sector_list != NULL )
1390
567
  {
1391
567
    libcdata_range_list_free(
1392
567
     &read_directory_sector_list,
1393
567
     NULL,
1394
567
     NULL );
1395
567
  }
1396
567
  if( directory_sector != NULL )
1397
567
  {
1398
567
    memory_free(
1399
567
     directory_sector );
1400
567
  }
1401
567
  libcdata_list_empty(
1402
567
   directory_entry_list,
1403
567
         (int (*)(intptr_t **, libcerror_error_t **)) &libolecf_directory_entry_free,
1404
567
   NULL );
1405
1406
567
  return( -1 );
1407
690
}
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