Coverage Report

Created: 2025-06-13 07:21

/src/libmdmp/libmdmp/libmdmp_file.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * File functions
3
 *
4
 * Copyright (C) 2014-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <narrow_string.h>
25
#include <types.h>
26
#include <wide_string.h>
27
28
#include "libmdmp_codepage.h"
29
#include "libmdmp_debug.h"
30
#include "libmdmp_definitions.h"
31
#include "libmdmp_io_handle.h"
32
#include "libmdmp_file.h"
33
#include "libmdmp_file_header.h"
34
#include "libmdmp_libbfio.h"
35
#include "libmdmp_libcdata.h"
36
#include "libmdmp_libcerror.h"
37
#include "libmdmp_libcnotify.h"
38
#include "libmdmp_stream.h"
39
#include "libmdmp_stream_descriptor.h"
40
41
/* Creates a file
42
 * Make sure the value file is referencing, is set to NULL
43
 * Returns 1 if successful or -1 on error
44
 */
45
int libmdmp_file_initialize(
46
     libmdmp_file_t **file,
47
     libcerror_error_t **error )
48
374
{
49
374
  libmdmp_internal_file_t *internal_file = NULL;
50
374
  static char *function                  = "libmdmp_file_initialize";
51
52
374
  if( file == NULL )
53
0
  {
54
0
    libcerror_error_set(
55
0
     error,
56
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
57
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
58
0
     "%s: invalid file.",
59
0
     function );
60
61
0
    return( -1 );
62
0
  }
63
374
  if( *file != NULL )
64
0
  {
65
0
    libcerror_error_set(
66
0
     error,
67
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
68
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
69
0
     "%s: invalid file value already set.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
374
  internal_file = memory_allocate_structure(
75
374
                   libmdmp_internal_file_t );
76
77
374
  if( internal_file == NULL )
78
0
  {
79
0
    libcerror_error_set(
80
0
     error,
81
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
82
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
83
0
     "%s: unable to create file.",
84
0
     function );
85
86
0
    goto on_error;
87
0
  }
88
374
  if( memory_set(
89
374
       internal_file,
90
374
       0,
91
374
       sizeof( libmdmp_internal_file_t ) ) == NULL )
92
0
  {
93
0
    libcerror_error_set(
94
0
     error,
95
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
96
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
97
0
     "%s: unable to clear file.",
98
0
     function );
99
100
0
    memory_free(
101
0
     internal_file );
102
103
0
    return( -1 );
104
0
  }
105
374
  if( libcdata_array_initialize(
106
374
       &( internal_file->streams_array ),
107
374
       0,
108
374
       error ) != 1 )
109
0
  {
110
0
    libcerror_error_set(
111
0
     error,
112
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
113
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
114
0
     "%s: unable to create streams array.",
115
0
     function );
116
117
0
    goto on_error;
118
0
  }
119
374
  if( libmdmp_io_handle_initialize(
120
374
       &( internal_file->io_handle ),
121
374
       error ) != 1 )
122
0
  {
123
0
    libcerror_error_set(
124
0
     error,
125
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
126
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
127
0
     "%s: unable to create IO handle.",
128
0
     function );
129
130
0
    goto on_error;
131
0
  }
132
374
  *file = (libmdmp_file_t *) internal_file;
133
134
374
  return( 1 );
135
136
0
on_error:
137
0
  if( internal_file != NULL )
138
0
  {
139
0
    if( internal_file->streams_array != NULL )
140
0
    {
141
0
      libcdata_array_free(
142
0
       &( internal_file->streams_array ),
143
0
       NULL,
144
0
       NULL );
145
0
    }
146
0
    memory_free(
147
0
     internal_file );
148
0
  }
149
0
  return( -1 );
150
374
}
151
152
/* Frees a file
153
 * Returns 1 if successful or -1 on error
154
 */
155
int libmdmp_file_free(
156
     libmdmp_file_t **file,
157
     libcerror_error_t **error )
158
374
{
159
374
  libmdmp_internal_file_t *internal_file = NULL;
160
374
  static char *function                  = "libmdmp_file_free";
161
374
  int result                             = 1;
162
163
374
  if( file == NULL )
164
0
  {
165
0
    libcerror_error_set(
166
0
     error,
167
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
168
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
169
0
     "%s: invalid file.",
170
0
     function );
171
172
0
    return( -1 );
173
0
  }
174
374
  if( *file != NULL )
175
374
  {
176
374
    internal_file = (libmdmp_internal_file_t *) *file;
177
178
374
    if( internal_file->file_io_handle != NULL )
179
0
    {
180
0
      if( libmdmp_file_close(
181
0
           *file,
182
0
           error ) != 0 )
183
0
      {
184
0
        libcerror_error_set(
185
0
         error,
186
0
         LIBCERROR_ERROR_DOMAIN_IO,
187
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
188
0
         "%s: unable to close file.",
189
0
         function );
190
191
0
        result = -1;
192
0
      }
193
0
    }
194
374
    *file = NULL;
195
196
374
    if( libcdata_array_free(
197
374
         &( internal_file->streams_array ),
198
374
         (int (*)(intptr_t **, libcerror_error_t **)) &libmdmp_stream_descriptor_free,
199
374
         error ) != 1 )
200
0
    {
201
0
      libcerror_error_set(
202
0
       error,
203
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
204
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
205
0
       "%s: unable to free streams array.",
206
0
       function );
207
208
0
      result = -1;
209
0
    }
210
374
    if( libmdmp_io_handle_free(
211
374
         &( internal_file->io_handle ),
212
374
         error ) != 1 )
213
0
    {
214
0
      libcerror_error_set(
215
0
       error,
216
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
217
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
218
0
       "%s: unable to free IO handle.",
219
0
       function );
220
221
0
      result = -1;
222
0
    }
223
374
    memory_free(
224
374
     internal_file );
225
374
  }
226
374
  return( result );
227
374
}
228
229
/* Signals the file to abort its current activity
230
 * Returns 1 if successful or -1 on error
231
 */
232
int libmdmp_file_signal_abort(
233
     libmdmp_file_t *file,
234
     libcerror_error_t **error )
235
0
{
236
0
  libmdmp_internal_file_t *internal_file = NULL;
237
0
  static char *function                  = "libmdmp_file_signal_abort";
238
239
0
  if( file == NULL )
240
0
  {
241
0
    libcerror_error_set(
242
0
     error,
243
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
244
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
245
0
     "%s: invalid file.",
246
0
     function );
247
248
0
    return( -1 );
249
0
  }
250
0
  internal_file = (libmdmp_internal_file_t *) file;
251
252
0
  if( internal_file->io_handle == NULL )
253
0
  {
254
0
    libcerror_error_set(
255
0
     error,
256
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
257
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
258
0
     "%s: invalid file - missing IO handle.",
259
0
     function );
260
261
0
    return( -1 );
262
0
  }
263
0
  internal_file->io_handle->abort = 1;
264
265
0
  return( 1 );
266
0
}
267
268
/* Opens a file
269
 * Returns 1 if successful or -1 on error
270
 */
271
int libmdmp_file_open(
272
     libmdmp_file_t *file,
273
     const char *filename,
274
     int access_flags,
275
     libcerror_error_t **error )
276
0
{
277
0
  libbfio_handle_t *file_io_handle       = NULL;
278
0
  libmdmp_internal_file_t *internal_file = NULL;
279
0
  static char *function                  = "libmdmp_file_open";
280
0
  size_t filename_length                 = 0;
281
282
0
  if( file == NULL )
283
0
  {
284
0
    libcerror_error_set(
285
0
     error,
286
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
287
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
288
0
     "%s: invalid file.",
289
0
     function );
290
291
0
    return( -1 );
292
0
  }
293
0
  internal_file = (libmdmp_internal_file_t *) file;
294
295
0
  if( filename == NULL )
296
0
  {
297
0
    libcerror_error_set(
298
0
     error,
299
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
300
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
301
0
     "%s: invalid filename.",
302
0
     function );
303
304
0
    return( -1 );
305
0
  }
306
0
  if( ( ( access_flags & LIBMDMP_ACCESS_FLAG_READ ) == 0 )
307
0
   && ( ( access_flags & LIBMDMP_ACCESS_FLAG_WRITE ) == 0 ) )
308
0
  {
309
0
    libcerror_error_set(
310
0
     error,
311
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
312
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
313
0
     "%s: unsupported access flags.",
314
0
     function );
315
316
0
    return( -1 );
317
0
  }
318
0
  if( ( access_flags & LIBMDMP_ACCESS_FLAG_WRITE ) != 0 )
319
0
  {
320
0
    libcerror_error_set(
321
0
     error,
322
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
323
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
324
0
     "%s: write access currently not supported.",
325
0
     function );
326
327
0
    return( -1 );
328
0
  }
329
0
  if( libbfio_file_initialize(
330
0
       &file_io_handle,
331
0
       error ) != 1 )
332
0
  {
333
0
    libcerror_error_set(
334
0
     error,
335
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
336
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
337
0
     "%s: unable to create file IO handle.",
338
0
     function );
339
340
0
    goto on_error;
341
0
  }
342
#if defined( HAVE_DEBUG_OUTPUT )
343
  if( libbfio_handle_set_track_offsets_read(
344
       file_io_handle,
345
       1,
346
       error ) != 1 )
347
  {
348
                libcerror_error_set(
349
                 error,
350
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
351
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
352
                 "%s: unable to set track offsets read in file IO handle.",
353
                 function );
354
355
    goto on_error;
356
  }
357
#endif
358
0
  filename_length = narrow_string_length(
359
0
                     filename );
360
361
0
  if( libbfio_file_set_name(
362
0
       file_io_handle,
363
0
       filename,
364
0
       filename_length + 1,
365
0
       error ) != 1 )
366
0
  {
367
0
                libcerror_error_set(
368
0
                 error,
369
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
370
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
371
0
                 "%s: unable to set filename in file IO handle.",
372
0
                 function );
373
374
0
    goto on_error;
375
0
  }
376
0
  if( libmdmp_file_open_file_io_handle(
377
0
       file,
378
0
       file_io_handle,
379
0
       access_flags,
380
0
       error ) != 1 )
381
0
  {
382
0
    libcerror_error_set(
383
0
     error,
384
0
     LIBCERROR_ERROR_DOMAIN_IO,
385
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
386
0
     "%s: unable to open file: %s.",
387
0
     function,
388
0
     filename );
389
390
0
    goto on_error;
391
0
  }
392
0
  internal_file->file_io_handle_created_in_library = 1;
393
394
0
  return( 1 );
395
396
0
on_error:
397
0
  if( file_io_handle != NULL )
398
0
  {
399
0
    libbfio_handle_free(
400
0
     &file_io_handle,
401
0
     NULL );
402
0
  }
403
0
  return( -1 );
404
0
}
405
406
#if defined( HAVE_WIDE_CHARACTER_TYPE )
407
408
/* Opens a file
409
 * Returns 1 if successful or -1 on error
410
 */
411
int libmdmp_file_open_wide(
412
     libmdmp_file_t *file,
413
     const wchar_t *filename,
414
     int access_flags,
415
     libcerror_error_t **error )
416
{
417
  libbfio_handle_t *file_io_handle       = NULL;
418
  libmdmp_internal_file_t *internal_file = NULL;
419
  static char *function                  = "libmdmp_file_open_wide";
420
  size_t filename_length                 = 0;
421
422
  if( file == NULL )
423
  {
424
    libcerror_error_set(
425
     error,
426
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
427
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
428
     "%s: invalid file.",
429
     function );
430
431
    return( -1 );
432
  }
433
  internal_file = (libmdmp_internal_file_t *) file;
434
435
  if( filename == NULL )
436
  {
437
    libcerror_error_set(
438
     error,
439
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
440
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
441
     "%s: invalid filename.",
442
     function );
443
444
    return( -1 );
445
  }
446
  if( ( ( access_flags & LIBMDMP_ACCESS_FLAG_READ ) == 0 )
447
   && ( ( access_flags & LIBMDMP_ACCESS_FLAG_WRITE ) == 0 ) )
448
  {
449
    libcerror_error_set(
450
     error,
451
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
452
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
453
     "%s: unsupported access flags.",
454
     function );
455
456
    return( -1 );
457
  }
458
  if( ( access_flags & LIBMDMP_ACCESS_FLAG_WRITE ) != 0 )
459
  {
460
    libcerror_error_set(
461
     error,
462
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
463
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
464
     "%s: write access currently not supported.",
465
     function );
466
467
    return( -1 );
468
  }
469
  if( libbfio_file_initialize(
470
       &file_io_handle,
471
       error ) != 1 )
472
  {
473
    libcerror_error_set(
474
     error,
475
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
476
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
477
     "%s: unable to create file IO handle.",
478
     function );
479
480
    goto on_error;
481
  }
482
#if defined( HAVE_DEBUG_OUTPUT )
483
  if( libbfio_handle_set_track_offsets_read(
484
       file_io_handle,
485
       1,
486
       error ) != 1 )
487
  {
488
                libcerror_error_set(
489
                 error,
490
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
491
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
492
                 "%s: unable to set track offsets read in file IO handle.",
493
                 function );
494
495
    goto on_error;
496
  }
497
#endif
498
  filename_length = wide_string_length(
499
                     filename );
500
501
  if( libbfio_file_set_name_wide(
502
       file_io_handle,
503
       filename,
504
       filename_length + 1,
505
       error ) != 1 )
506
  {
507
                libcerror_error_set(
508
                 error,
509
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
510
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
511
                 "%s: unable to set filename in file IO handle.",
512
                 function );
513
514
    goto on_error;
515
  }
516
  if( libmdmp_file_open_file_io_handle(
517
       file,
518
       file_io_handle,
519
       access_flags,
520
       error ) != 1 )
521
  {
522
    libcerror_error_set(
523
     error,
524
     LIBCERROR_ERROR_DOMAIN_IO,
525
     LIBCERROR_IO_ERROR_OPEN_FAILED,
526
     "%s: unable to open file: %ls.",
527
     function,
528
     filename );
529
530
    goto on_error;
531
  }
532
  internal_file->file_io_handle_created_in_library = 1;
533
534
  return( 1 );
535
536
on_error:
537
  if( file_io_handle != NULL )
538
  {
539
    libbfio_handle_free(
540
     &file_io_handle,
541
     NULL );
542
  }
543
  return( -1 );
544
}
545
546
#endif
547
548
/* Opens a file using a Basic File IO (bfio) handle
549
 * Returns 1 if successful or -1 on error
550
 */
551
int libmdmp_file_open_file_io_handle(
552
     libmdmp_file_t *file,
553
     libbfio_handle_t *file_io_handle,
554
     int access_flags,
555
     libcerror_error_t **error )
556
374
{
557
374
  libmdmp_internal_file_t *internal_file = NULL;
558
374
  static char *function                  = "libmdmp_file_open_file_io_handle";
559
374
  int bfio_access_flags                  = 0;
560
374
  int file_io_handle_is_open             = 0;
561
562
374
  if( file == NULL )
563
0
  {
564
0
    libcerror_error_set(
565
0
     error,
566
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
567
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
568
0
     "%s: invalid file.",
569
0
     function );
570
571
0
    return( -1 );
572
0
  }
573
374
  internal_file = (libmdmp_internal_file_t *) file;
574
575
374
  if( internal_file->file_io_handle != NULL )
576
0
  {
577
0
    libcerror_error_set(
578
0
     error,
579
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
580
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
581
0
     "%s: invalid file - file IO handle already set.",
582
0
     function );
583
584
0
    return( -1 );
585
0
  }
586
374
  if( file_io_handle == NULL )
587
0
  {
588
0
    libcerror_error_set(
589
0
     error,
590
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
591
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
592
0
     "%s: invalid file IO handle.",
593
0
     function );
594
595
0
    return( -1 );
596
0
  }
597
374
  if( ( ( access_flags & LIBMDMP_ACCESS_FLAG_READ ) == 0 )
598
374
   && ( ( access_flags & LIBMDMP_ACCESS_FLAG_WRITE ) == 0 ) )
599
0
  {
600
0
    libcerror_error_set(
601
0
     error,
602
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
603
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
604
0
     "%s: unsupported access flags.",
605
0
     function );
606
607
0
    return( -1 );
608
0
  }
609
374
  if( ( access_flags & LIBMDMP_ACCESS_FLAG_WRITE ) != 0 )
610
0
  {
611
0
    libcerror_error_set(
612
0
     error,
613
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
614
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
615
0
     "%s: write access currently not supported.",
616
0
     function );
617
618
0
    return( -1 );
619
0
  }
620
374
  if( ( access_flags & LIBMDMP_ACCESS_FLAG_READ ) != 0 )
621
374
  {
622
374
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
623
374
  }
624
374
  internal_file->file_io_handle = file_io_handle;
625
626
374
  file_io_handle_is_open = libbfio_handle_is_open(
627
374
                            internal_file->file_io_handle,
628
374
                            error );
629
630
374
  if( file_io_handle_is_open == -1 )
631
0
  {
632
0
    libcerror_error_set(
633
0
     error,
634
0
     LIBCERROR_ERROR_DOMAIN_IO,
635
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
636
0
     "%s: unable to determine if file IO handle is open.",
637
0
     function );
638
639
0
    goto on_error;
640
0
  }
641
374
  else if( file_io_handle_is_open == 0 )
642
374
  {
643
374
    if( libbfio_handle_open(
644
374
         internal_file->file_io_handle,
645
374
         bfio_access_flags,
646
374
         error ) != 1 )
647
0
    {
648
0
      libcerror_error_set(
649
0
       error,
650
0
       LIBCERROR_ERROR_DOMAIN_IO,
651
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
652
0
       "%s: unable to open file IO handle.",
653
0
       function );
654
655
0
      goto on_error;
656
0
    }
657
374
    internal_file->file_io_handle_opened_in_library = 1;
658
374
  }
659
374
  if( libmdmp_file_open_read(
660
374
       internal_file,
661
374
       file_io_handle,
662
374
       error ) != 1 )
663
208
  {
664
208
    libcerror_error_set(
665
208
     error,
666
208
     LIBCERROR_ERROR_DOMAIN_IO,
667
208
     LIBCERROR_IO_ERROR_READ_FAILED,
668
208
     "%s: unable to read from file handle.",
669
208
     function );
670
671
208
    goto on_error;
672
208
  }
673
166
  internal_file->file_io_handle = file_io_handle;
674
675
166
  return( 1 );
676
677
208
on_error:
678
208
  if( ( file_io_handle_is_open == 0 )
679
208
   && ( internal_file->file_io_handle_opened_in_library != 0 ) )
680
208
  {
681
208
    libbfio_handle_close(
682
208
     file_io_handle,
683
208
     error );
684
685
208
    internal_file->file_io_handle_opened_in_library = 0;
686
208
  }
687
208
  internal_file->file_io_handle = NULL;
688
689
208
  return( -1 );
690
374
}
691
692
/* Closes a file
693
 * Returns 0 if successful or -1 on error
694
 */
695
int libmdmp_file_close(
696
     libmdmp_file_t *file,
697
     libcerror_error_t **error )
698
166
{
699
166
  libmdmp_internal_file_t *internal_file = NULL;
700
166
  static char *function                  = "libmdmp_file_close";
701
166
  int result                             = 0;
702
703
166
  if( file == NULL )
704
0
  {
705
0
    libcerror_error_set(
706
0
     error,
707
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
708
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
709
0
     "%s: invalid file.",
710
0
     function );
711
712
0
    return( -1 );
713
0
  }
714
166
  internal_file = (libmdmp_internal_file_t *) file;
715
716
166
  if( internal_file->file_io_handle == NULL )
717
0
  {
718
0
    libcerror_error_set(
719
0
     error,
720
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
721
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
722
0
     "%s: invalid file - missing file IO handle.",
723
0
     function );
724
725
0
    return( -1 );
726
0
  }
727
#if defined( HAVE_DEBUG_OUTPUT )
728
  if( libcnotify_verbose != 0 )
729
  {
730
    if( internal_file->file_io_handle_created_in_library != 0 )
731
    {
732
      if( libmdmp_debug_print_read_offsets(
733
           internal_file->file_io_handle,
734
           error ) != 1 )
735
      {
736
        libcerror_error_set(
737
         error,
738
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
739
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
740
         "%s: unable to print the read offsets.",
741
         function );
742
743
        result = -1;
744
      }
745
    }
746
  }
747
#endif
748
166
  if( internal_file->file_io_handle_opened_in_library != 0 )
749
166
  {
750
166
    if( libbfio_handle_close(
751
166
         internal_file->file_io_handle,
752
166
         error ) != 0 )
753
0
    {
754
0
      libcerror_error_set(
755
0
       error,
756
0
       LIBCERROR_ERROR_DOMAIN_IO,
757
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
758
0
       "%s: unable to close file IO handle.",
759
0
       function );
760
761
0
      result = -1;
762
0
    }
763
166
    internal_file->file_io_handle_opened_in_library = 0;
764
166
  }
765
166
  if( internal_file->file_io_handle_created_in_library != 0 )
766
0
  {
767
0
    if( libbfio_handle_free(
768
0
         &( internal_file->file_io_handle ),
769
0
         error ) != 1 )
770
0
    {
771
0
      libcerror_error_set(
772
0
       error,
773
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
774
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
775
0
       "%s: unable to free file IO handle.",
776
0
       function );
777
778
0
      result = -1;
779
0
    }
780
0
    internal_file->file_io_handle_created_in_library = 0;
781
0
  }
782
166
  internal_file->file_io_handle = NULL;
783
784
166
  if( libmdmp_io_handle_clear(
785
166
       internal_file->io_handle,
786
166
       error ) != 1 )
787
0
  {
788
0
    libcerror_error_set(
789
0
     error,
790
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
791
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
792
0
     "%s: unable to clear IO handle.",
793
0
     function );
794
795
0
    result = -1;
796
0
  }
797
166
  if( libmdmp_file_header_free(
798
166
       &( internal_file->file_header ),
799
166
       error ) != 1 )
800
0
  {
801
0
    libcerror_error_set(
802
0
     error,
803
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
804
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
805
0
     "%s: unable to free file header.",
806
0
     function );
807
808
0
    result = -1;
809
0
  }
810
166
  if( libcdata_array_resize(
811
166
       internal_file->streams_array,
812
166
       0,
813
166
       (int (*)(intptr_t **, libcerror_error_t **)) &libmdmp_stream_descriptor_free,
814
166
       error ) != 1 )
815
0
  {
816
0
    libcerror_error_set(
817
0
     error,
818
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
819
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
820
0
     "%s: unable to resize streams array.",
821
0
     function );
822
823
0
    result = -1;
824
0
  }
825
166
  return( result );
826
166
}
827
828
/* Opens a file for reading
829
 * Returns 1 if successful or -1 on error
830
 */
831
int libmdmp_file_open_read(
832
     libmdmp_internal_file_t *internal_file,
833
     libbfio_handle_t *file_io_handle,
834
     libcerror_error_t **error )
835
374
{
836
374
  static char *function = "libmdmp_file_open_read";
837
838
374
  if( internal_file == NULL )
839
0
  {
840
0
    libcerror_error_set(
841
0
     error,
842
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
843
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
844
0
     "%s: invalid file.",
845
0
     function );
846
847
0
    return( -1 );
848
0
  }
849
374
  if( internal_file->io_handle == NULL )
850
0
  {
851
0
    libcerror_error_set(
852
0
     error,
853
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
854
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
855
0
     "%s: invalid file - missing IO handle.",
856
0
     function );
857
858
0
    return( -1 );
859
0
  }
860
374
  if( internal_file->file_header != NULL )
861
0
  {
862
0
    libcerror_error_set(
863
0
     error,
864
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
865
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
866
0
     "%s: invalid file - file header value already set.",
867
0
     function );
868
869
0
    return( -1 );
870
0
  }
871
374
  if( internal_file->io_handle->abort != 0 )
872
0
  {
873
0
    internal_file->io_handle->abort = 0;
874
0
  }
875
#if defined( HAVE_DEBUG_OUTPUT )
876
  if( libcnotify_verbose != 0 )
877
  {
878
    libcnotify_printf(
879
     "Reading file header:\n" );
880
  }
881
#endif
882
374
  if( libmdmp_file_header_initialize(
883
374
       &( internal_file->file_header ),
884
374
       error ) != 1 )
885
0
  {
886
0
    libcerror_error_set(
887
0
     error,
888
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
889
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
890
0
     "%s: unable to create file header.",
891
0
     function );
892
893
0
    goto on_error;
894
0
  }
895
374
  if( libmdmp_file_header_read_file_io_handle(
896
374
       internal_file->file_header,
897
374
       file_io_handle,
898
374
       error ) != 1 )
899
40
  {
900
40
    libcerror_error_set(
901
40
     error,
902
40
     LIBCERROR_ERROR_DOMAIN_IO,
903
40
     LIBCERROR_IO_ERROR_READ_FAILED,
904
40
     "%s: unable to read file header.",
905
40
     function );
906
907
40
    goto on_error;
908
40
  }
909
334
  internal_file->io_handle->version = internal_file->file_header->version;
910
911
#if defined( HAVE_DEBUG_OUTPUT )
912
  if( libcnotify_verbose != 0 )
913
  {
914
    libcnotify_printf(
915
     "Reading streams directory:\n" );
916
  }
917
#endif
918
334
  if( libmdmp_io_handle_read_streams_directory(
919
334
       internal_file->io_handle,
920
334
       file_io_handle,
921
334
       internal_file->file_header->streams_directory_offset,
922
334
       internal_file->file_header->number_of_streams,
923
334
       internal_file->streams_array,
924
334
       error ) != 1 )
925
168
  {
926
168
    libcerror_error_set(
927
168
     error,
928
168
     LIBCERROR_ERROR_DOMAIN_IO,
929
168
     LIBCERROR_IO_ERROR_READ_FAILED,
930
168
     "%s: unable to read file header.",
931
168
     function );
932
933
168
    goto on_error;
934
168
  }
935
/* TODO */
936
166
  return( 1 );
937
938
208
on_error:
939
208
  if( internal_file->file_header != NULL )
940
208
  {
941
208
    libmdmp_file_header_free(
942
208
     &( internal_file->file_header ),
943
208
     NULL );
944
208
  }
945
208
  return( -1 );
946
334
}
947
948
/* Retrieves the number of streams
949
 * Returns 1 if successful or -1 on error
950
 */
951
int libmdmp_file_get_number_of_streams(
952
     libmdmp_file_t *file,
953
     int *number_of_streams,
954
     libcerror_error_t **error )
955
0
{
956
0
  libmdmp_internal_file_t *internal_file = NULL;
957
0
  static char *function                  = "libmdmp_file_get_number_of_streams";
958
959
0
  if( file == NULL )
960
0
  {
961
0
    libcerror_error_set(
962
0
     error,
963
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
964
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
965
0
     "%s: invalid file.",
966
0
     function );
967
968
0
    return( -1 );
969
0
  }
970
0
  internal_file = (libmdmp_internal_file_t *) file;
971
972
0
  if( libcdata_array_get_number_of_entries(
973
0
       internal_file->streams_array,
974
0
       number_of_streams,
975
0
       error ) != 1 )
976
0
  {
977
0
    libcerror_error_set(
978
0
     error,
979
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
980
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
981
0
     "%s: unable to retrieve number of streams.",
982
0
     function );
983
984
0
    return( -1 );
985
0
  }
986
0
  return( 1 );
987
0
}
988
989
/* Retrieves a specific stream
990
 * Returns 1 if successful or -1 on error
991
 */
992
int libmdmp_file_get_stream(
993
     libmdmp_file_t *file,
994
     int stream_index,
995
     libmdmp_stream_t **stream,
996
     libcerror_error_t **error )
997
0
{
998
0
  libmdmp_internal_file_t *internal_file         = NULL;
999
0
  libmdmp_stream_descriptor_t *stream_descriptor = NULL;
1000
0
  static char *function                          = "libmdmp_file_get_stream";
1001
1002
0
  if( file == NULL )
1003
0
  {
1004
0
    libcerror_error_set(
1005
0
     error,
1006
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1007
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1008
0
     "%s: invalid file.",
1009
0
     function );
1010
1011
0
    return( -1 );
1012
0
  }
1013
0
  internal_file = (libmdmp_internal_file_t *) file;
1014
1015
0
  if( stream == NULL )
1016
0
  {
1017
0
    libcerror_error_set(
1018
0
     error,
1019
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1020
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1021
0
     "%s: invalid stream.",
1022
0
     function );
1023
1024
0
    return( -1 );
1025
0
  }
1026
0
  if( *stream != NULL )
1027
0
  {
1028
0
    libcerror_error_set(
1029
0
     error,
1030
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1031
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1032
0
     "%s: invalid stream value already set.",
1033
0
     function );
1034
1035
0
    return( -1 );
1036
0
  }
1037
0
  if( libcdata_array_get_entry_by_index(
1038
0
       internal_file->streams_array,
1039
0
       stream_index,
1040
0
       (intptr_t **) &stream_descriptor,
1041
0
       error ) != 1 )
1042
0
  {
1043
0
    libcerror_error_set(
1044
0
     error,
1045
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1046
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1047
0
     "%s: unable to retrieve stream descriptor: %d.",
1048
0
     function,
1049
0
     stream_index );
1050
1051
0
    return( -1 );
1052
0
  }
1053
0
  if( libmdmp_stream_initialize(
1054
0
       stream,
1055
0
       internal_file->io_handle,
1056
0
       internal_file->file_io_handle,
1057
0
       stream_descriptor,
1058
0
       error ) != 1 )
1059
0
  {
1060
0
    libcerror_error_set(
1061
0
     error,
1062
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1063
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1064
0
     "%s: unable to create stream.",
1065
0
     function );
1066
1067
0
    return( -1 );
1068
0
  }
1069
0
  return( 1 );
1070
0
}
1071
1072
/* Retrieves a specific stream by type
1073
 * Returns 1 if successful, 0 if no such stream or -1 on error
1074
 */
1075
int libmdmp_file_get_stream_by_type(
1076
     libmdmp_file_t *file,
1077
     uint32_t stream_type,
1078
     libmdmp_stream_t **stream,
1079
     libcerror_error_t **error )
1080
0
{
1081
0
  libmdmp_internal_file_t *internal_file         = NULL;
1082
0
  libmdmp_stream_descriptor_t *stream_descriptor = NULL;
1083
0
  static char *function                          = "libmdmp_file_get_stream_by_type";
1084
0
  int number_of_streams                          = 0;
1085
0
  int stream_index                               = 0;
1086
1087
0
  if( file == NULL )
1088
0
  {
1089
0
    libcerror_error_set(
1090
0
     error,
1091
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1092
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1093
0
     "%s: invalid file.",
1094
0
     function );
1095
1096
0
    return( -1 );
1097
0
  }
1098
0
  internal_file = (libmdmp_internal_file_t *) file;
1099
1100
0
  if( stream == NULL )
1101
0
  {
1102
0
    libcerror_error_set(
1103
0
     error,
1104
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1105
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1106
0
     "%s: invalid stream.",
1107
0
     function );
1108
1109
0
    return( -1 );
1110
0
  }
1111
0
  if( *stream != NULL )
1112
0
  {
1113
0
    libcerror_error_set(
1114
0
     error,
1115
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1116
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1117
0
     "%s: invalid stream value already set.",
1118
0
     function );
1119
1120
0
    return( -1 );
1121
0
  }
1122
0
  if( libcdata_array_get_number_of_entries(
1123
0
       internal_file->streams_array,
1124
0
       &number_of_streams,
1125
0
       error ) != 1 )
1126
0
  {
1127
0
    libcerror_error_set(
1128
0
     error,
1129
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1130
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1131
0
     "%s: unable to retrieve number of streams.",
1132
0
     function );
1133
1134
0
    return( -1 );
1135
0
  }
1136
0
  for( stream_index = 0;
1137
0
       stream_index < number_of_streams;
1138
0
       stream_index++ )
1139
0
  {
1140
0
    if( libcdata_array_get_entry_by_index(
1141
0
         internal_file->streams_array,
1142
0
         stream_index,
1143
0
         (intptr_t **) &stream_descriptor,
1144
0
         error ) != 1 )
1145
0
    {
1146
0
      libcerror_error_set(
1147
0
       error,
1148
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1149
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1150
0
       "%s: unable to retrieve stream descriptor: %d.",
1151
0
       function,
1152
0
       stream_index );
1153
1154
0
      return( -1 );
1155
0
    }
1156
0
    if( stream_descriptor == NULL )
1157
0
    {
1158
0
      libcerror_error_set(
1159
0
       error,
1160
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1161
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1162
0
       "%s: missing stream descriptor: %d.",
1163
0
       function,
1164
0
       stream_index );
1165
1166
0
      return( -1 );
1167
0
    }
1168
0
    if( stream_type == stream_descriptor->type )
1169
0
    {
1170
0
      if( libmdmp_stream_initialize(
1171
0
           stream,
1172
0
           internal_file->io_handle,
1173
0
           internal_file->file_io_handle,
1174
0
           stream_descriptor,
1175
0
           error ) != 1 )
1176
0
      {
1177
0
        libcerror_error_set(
1178
0
         error,
1179
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1180
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1181
0
         "%s: unable to create stream.",
1182
0
         function );
1183
1184
0
        return( -1 );
1185
0
      }
1186
0
      return( 1 );
1187
0
    }
1188
0
  }
1189
0
  return( 0 );
1190
0
}
1191