Coverage Report

Created: 2024-10-02 06:58

/src/libevtx/libevtx/libevtx_file.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * File functions
3
 *
4
 * Copyright (C) 2011-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 "libevtx_chunks_table.h"
29
#include "libevtx_codepage.h"
30
#include "libevtx_chunk.h"
31
#include "libevtx_debug.h"
32
#include "libevtx_definitions.h"
33
#include "libevtx_i18n.h"
34
#include "libevtx_io_handle.h"
35
#include "libevtx_file.h"
36
#include "libevtx_libbfio.h"
37
#include "libevtx_libcerror.h"
38
#include "libevtx_libcnotify.h"
39
#include "libevtx_libfcache.h"
40
#include "libevtx_libfdata.h"
41
#include "libevtx_record.h"
42
#include "libevtx_record_values.h"
43
44
/* Creates a file
45
 * Make sure the value file is referencing, is set to NULL
46
 * Returns 1 if successful or -1 on error
47
 */
48
int libevtx_file_initialize(
49
     libevtx_file_t **file,
50
     libcerror_error_t **error )
51
2.80k
{
52
2.80k
  libevtx_internal_file_t *internal_file = NULL;
53
2.80k
  static char *function                  = "libevtx_file_initialize";
54
55
2.80k
  if( file == NULL )
56
0
  {
57
0
    libcerror_error_set(
58
0
     error,
59
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
60
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
61
0
     "%s: invalid file.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
2.80k
  if( *file != NULL )
67
0
  {
68
0
    libcerror_error_set(
69
0
     error,
70
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
71
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
72
0
     "%s: invalid file value already set.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
2.80k
  internal_file = memory_allocate_structure(
78
2.80k
                   libevtx_internal_file_t );
79
80
2.80k
  if( internal_file == NULL )
81
0
  {
82
0
    libcerror_error_set(
83
0
     error,
84
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
85
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
86
0
     "%s: unable to create file.",
87
0
     function );
88
89
0
    goto on_error;
90
0
  }
91
2.80k
  if( memory_set(
92
2.80k
       internal_file,
93
2.80k
       0,
94
2.80k
       sizeof( libevtx_internal_file_t ) ) == NULL )
95
0
  {
96
0
    libcerror_error_set(
97
0
     error,
98
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
99
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
100
0
     "%s: unable to clear file.",
101
0
     function );
102
103
0
    memory_free(
104
0
     internal_file );
105
106
0
    return( -1 );
107
0
  }
108
2.80k
  if( libevtx_io_handle_initialize(
109
2.80k
       &( internal_file->io_handle ),
110
2.80k
       error ) != 1 )
111
0
  {
112
0
    libcerror_error_set(
113
0
     error,
114
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
115
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
116
0
     "%s: unable to create IO handle.",
117
0
     function );
118
119
0
    goto on_error;
120
0
  }
121
2.80k
  if( libevtx_i18n_initialize(
122
2.80k
       error ) != 1 )
123
0
  {
124
0
    libcerror_error_set(
125
0
     error,
126
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
127
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
128
0
     "%s: unable to initalize internationalization (i18n).",
129
0
     function );
130
131
0
    goto on_error;
132
0
  }
133
2.80k
  *file = (libevtx_file_t *) internal_file;
134
135
2.80k
  return( 1 );
136
137
0
on_error:
138
0
  if( internal_file != NULL )
139
0
  {
140
0
    if( internal_file->io_handle != NULL )
141
0
    {
142
0
      libevtx_io_handle_free(
143
0
       &( internal_file->io_handle ),
144
0
       NULL );
145
0
    }
146
0
    memory_free(
147
0
     internal_file );
148
0
  }
149
0
  return( -1 );
150
2.80k
}
151
152
/* Frees a file
153
 * Returns 1 if successful or -1 on error
154
 */
155
int libevtx_file_free(
156
     libevtx_file_t **file,
157
     libcerror_error_t **error )
158
2.80k
{
159
2.80k
  libevtx_internal_file_t *internal_file = NULL;
160
2.80k
  static char *function                  = "libevtx_file_free";
161
2.80k
  int result                             = 1;
162
163
2.80k
  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
2.80k
  if( *file != NULL )
175
2.80k
  {
176
2.80k
    internal_file = (libevtx_internal_file_t *) *file;
177
178
2.80k
    if( internal_file->file_io_handle != NULL )
179
0
    {
180
0
      if( libevtx_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
2.80k
    *file = NULL;
195
196
2.80k
    if( libevtx_io_handle_free(
197
2.80k
         &( internal_file->io_handle ),
198
2.80k
         error ) != 1 )
199
0
    {
200
0
      libcerror_error_set(
201
0
       error,
202
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
203
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
204
0
       "%s: unable to free IO handle.",
205
0
       function );
206
207
0
      result = -1;
208
0
    }
209
2.80k
    memory_free(
210
2.80k
     internal_file );
211
2.80k
  }
212
2.80k
  return( result );
213
2.80k
}
214
215
/* Signals a file to abort its current activity
216
 * Returns 1 if successful or -1 on error
217
 */
218
int libevtx_file_signal_abort(
219
     libevtx_file_t *file,
220
     libcerror_error_t **error )
221
0
{
222
0
  libevtx_internal_file_t *internal_file = NULL;
223
0
  static char *function                  = "libevtx_file_signal_abort";
224
225
0
  if( file == NULL )
226
0
  {
227
0
    libcerror_error_set(
228
0
     error,
229
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
230
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
231
0
     "%s: invalid file.",
232
0
     function );
233
234
0
    return( -1 );
235
0
  }
236
0
  internal_file = (libevtx_internal_file_t *) file;
237
238
0
  if( internal_file->io_handle == NULL )
239
0
  {
240
0
    libcerror_error_set(
241
0
     error,
242
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
243
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
244
0
     "%s: invalid file - missing IO handle.",
245
0
     function );
246
247
0
    return( -1 );
248
0
  }
249
0
  internal_file->io_handle->abort = 1;
250
251
0
  return( 1 );
252
0
}
253
254
/* Opens a file
255
 * Returns 1 if successful or -1 on error
256
 */
257
int libevtx_file_open(
258
     libevtx_file_t *file,
259
     const char *filename,
260
     int access_flags,
261
     libcerror_error_t **error )
262
0
{
263
0
  libbfio_handle_t *file_io_handle       = NULL;
264
0
  libevtx_internal_file_t *internal_file = NULL;
265
0
  static char *function                  = "libevtx_file_open";
266
0
  size_t filename_length                 = 0;
267
268
0
  if( file == NULL )
269
0
  {
270
0
    libcerror_error_set(
271
0
     error,
272
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
273
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
274
0
     "%s: invalid file.",
275
0
     function );
276
277
0
    return( -1 );
278
0
  }
279
0
  internal_file = (libevtx_internal_file_t *) file;
280
281
0
  if( filename == NULL )
282
0
  {
283
0
    libcerror_error_set(
284
0
     error,
285
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
286
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
287
0
     "%s: invalid filename.",
288
0
     function );
289
290
0
    return( -1 );
291
0
  }
292
0
  if( ( ( access_flags & LIBEVTX_ACCESS_FLAG_READ ) == 0 )
293
0
   && ( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) == 0 ) )
294
0
  {
295
0
    libcerror_error_set(
296
0
     error,
297
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
298
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
299
0
     "%s: unsupported access flags.",
300
0
     function );
301
302
0
    return( -1 );
303
0
  }
304
0
  if( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) != 0 )
305
0
  {
306
0
    libcerror_error_set(
307
0
     error,
308
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
309
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
310
0
     "%s: write access currently not supported.",
311
0
     function );
312
313
0
    return( -1 );
314
0
  }
315
0
  if( libbfio_file_initialize(
316
0
       &file_io_handle,
317
0
       error ) != 1 )
318
0
  {
319
0
    libcerror_error_set(
320
0
     error,
321
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
322
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
323
0
     "%s: unable to create file IO handle.",
324
0
     function );
325
326
0
    goto on_error;
327
0
  }
328
#if defined( HAVE_DEBUG_OUTPUT )
329
  if( libbfio_handle_set_track_offsets_read(
330
       file_io_handle,
331
       1,
332
       error ) != 1 )
333
  {
334
                libcerror_error_set(
335
                 error,
336
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
337
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
338
                 "%s: unable to set track offsets read in file IO handle.",
339
                 function );
340
341
    goto on_error;
342
  }
343
#endif
344
0
  filename_length = narrow_string_length(
345
0
                     filename );
346
347
0
  if( libbfio_file_set_name(
348
0
       file_io_handle,
349
0
       filename,
350
0
       filename_length + 1,
351
0
       error ) != 1 )
352
0
  {
353
0
                libcerror_error_set(
354
0
                 error,
355
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
356
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
357
0
                 "%s: unable to set filename in file IO handle.",
358
0
                 function );
359
360
0
    goto on_error;
361
0
  }
362
0
  if( libevtx_file_open_file_io_handle(
363
0
       file,
364
0
       file_io_handle,
365
0
       access_flags,
366
0
       error ) != 1 )
367
0
  {
368
0
    libcerror_error_set(
369
0
     error,
370
0
     LIBCERROR_ERROR_DOMAIN_IO,
371
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
372
0
     "%s: unable to open file: %s.",
373
0
     function,
374
0
     filename );
375
376
0
    goto on_error;
377
0
  }
378
0
  internal_file->file_io_handle_created_in_library = 1;
379
380
0
  return( 1 );
381
382
0
on_error:
383
0
  if( file_io_handle != NULL )
384
0
  {
385
0
    libbfio_handle_free(
386
0
     &file_io_handle,
387
0
     NULL );
388
0
  }
389
0
  return( -1 );
390
0
}
391
392
#if defined( HAVE_WIDE_CHARACTER_TYPE )
393
394
/* Opens a file
395
 * Returns 1 if successful or -1 on error
396
 */
397
int libevtx_file_open_wide(
398
     libevtx_file_t *file,
399
     const wchar_t *filename,
400
     int access_flags,
401
     libcerror_error_t **error )
402
{
403
  libbfio_handle_t *file_io_handle       = NULL;
404
  libevtx_internal_file_t *internal_file = NULL;
405
  static char *function                  = "libevtx_file_open_wide";
406
  size_t filename_length                 = 0;
407
408
  if( file == NULL )
409
  {
410
    libcerror_error_set(
411
     error,
412
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
413
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
414
     "%s: invalid file.",
415
     function );
416
417
    return( -1 );
418
  }
419
  internal_file = (libevtx_internal_file_t *) file;
420
421
  if( filename == NULL )
422
  {
423
    libcerror_error_set(
424
     error,
425
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
426
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
427
     "%s: invalid filename.",
428
     function );
429
430
    return( -1 );
431
  }
432
  if( ( ( access_flags & LIBEVTX_ACCESS_FLAG_READ ) == 0 )
433
   && ( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) == 0 ) )
434
  {
435
    libcerror_error_set(
436
     error,
437
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
438
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
439
     "%s: unsupported access flags.",
440
     function );
441
442
    return( -1 );
443
  }
444
  if( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) != 0 )
445
  {
446
    libcerror_error_set(
447
     error,
448
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
449
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
450
     "%s: write access currently not supported.",
451
     function );
452
453
    return( -1 );
454
  }
455
  if( libbfio_file_initialize(
456
       &file_io_handle,
457
       error ) != 1 )
458
  {
459
    libcerror_error_set(
460
     error,
461
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
462
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
463
     "%s: unable to create file IO handle.",
464
     function );
465
466
    goto on_error;
467
  }
468
#if defined( HAVE_DEBUG_OUTPUT )
469
  if( libbfio_handle_set_track_offsets_read(
470
       file_io_handle,
471
       1,
472
       error ) != 1 )
473
  {
474
                libcerror_error_set(
475
                 error,
476
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
477
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
478
                 "%s: unable to set track offsets read in file IO handle.",
479
                 function );
480
481
    goto on_error;
482
  }
483
#endif
484
  filename_length = wide_string_length(
485
                     filename );
486
487
  if( libbfio_file_set_name_wide(
488
       file_io_handle,
489
       filename,
490
       filename_length + 1,
491
       error ) != 1 )
492
  {
493
                libcerror_error_set(
494
                 error,
495
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
496
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
497
                 "%s: unable to set filename in file IO handle.",
498
                 function );
499
500
    goto on_error;
501
  }
502
  if( libevtx_file_open_file_io_handle(
503
       file,
504
       file_io_handle,
505
       access_flags,
506
       error ) != 1 )
507
  {
508
    libcerror_error_set(
509
     error,
510
     LIBCERROR_ERROR_DOMAIN_IO,
511
     LIBCERROR_IO_ERROR_OPEN_FAILED,
512
     "%s: unable to open file: %ls.",
513
     function,
514
     filename );
515
516
    goto on_error;
517
  }
518
  internal_file->file_io_handle_created_in_library = 1;
519
520
  return( 1 );
521
522
on_error:
523
  if( file_io_handle != NULL )
524
  {
525
    libbfio_handle_free(
526
     &file_io_handle,
527
     NULL );
528
  }
529
  return( -1 );
530
}
531
532
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
533
534
/* Opens a file using a Basic File IO (bfio) handle
535
 * Returns 1 if successful or -1 on error
536
 */
537
int libevtx_file_open_file_io_handle(
538
     libevtx_file_t *file,
539
     libbfio_handle_t *file_io_handle,
540
     int access_flags,
541
     libcerror_error_t **error )
542
2.80k
{
543
2.80k
  libevtx_internal_file_t *internal_file   = NULL;
544
2.80k
  static char *function                    = "libevtx_file_open_file_io_handle";
545
2.80k
  uint8_t file_io_handle_opened_in_library = 0;
546
2.80k
  int bfio_access_flags                    = 0;
547
2.80k
  int file_io_handle_is_open               = 0;
548
549
2.80k
  if( file == 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 file.",
556
0
     function );
557
558
0
    return( -1 );
559
0
  }
560
2.80k
  internal_file = (libevtx_internal_file_t *) file;
561
562
2.80k
  if( internal_file->file_io_handle != NULL )
563
0
  {
564
0
    libcerror_error_set(
565
0
     error,
566
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
567
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
568
0
     "%s: invalid file - file IO handle already set.",
569
0
     function );
570
571
0
    return( -1 );
572
0
  }
573
2.80k
  if( file_io_handle == NULL )
574
0
  {
575
0
    libcerror_error_set(
576
0
     error,
577
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
578
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
579
0
     "%s: invalid file IO handle.",
580
0
     function );
581
582
0
    return( -1 );
583
0
  }
584
2.80k
  if( ( ( access_flags & LIBEVTX_ACCESS_FLAG_READ ) == 0 )
585
2.80k
   && ( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) == 0 ) )
586
0
  {
587
0
    libcerror_error_set(
588
0
     error,
589
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
590
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
591
0
     "%s: unsupported access flags.",
592
0
     function );
593
594
0
    return( -1 );
595
0
  }
596
2.80k
  if( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) != 0 )
597
0
  {
598
0
    libcerror_error_set(
599
0
     error,
600
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
601
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
602
0
     "%s: write access currently not supported.",
603
0
     function );
604
605
0
    return( -1 );
606
0
  }
607
2.80k
  if( ( access_flags & LIBEVTX_ACCESS_FLAG_READ ) != 0 )
608
2.80k
  {
609
2.80k
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
610
2.80k
  }
611
2.80k
  file_io_handle_is_open = libbfio_handle_is_open(
612
2.80k
                            file_io_handle,
613
2.80k
                            error );
614
615
2.80k
  if( file_io_handle_is_open == -1 )
616
0
  {
617
0
    libcerror_error_set(
618
0
     error,
619
0
     LIBCERROR_ERROR_DOMAIN_IO,
620
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
621
0
     "%s: unable to open file.",
622
0
     function );
623
624
0
    goto on_error;
625
0
  }
626
2.80k
  else if( file_io_handle_is_open == 0 )
627
2.80k
  {
628
2.80k
    if( libbfio_handle_open(
629
2.80k
         file_io_handle,
630
2.80k
         bfio_access_flags,
631
2.80k
         error ) != 1 )
632
0
    {
633
0
      libcerror_error_set(
634
0
       error,
635
0
       LIBCERROR_ERROR_DOMAIN_IO,
636
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
637
0
       "%s: unable to open file IO handle.",
638
0
       function );
639
640
0
      goto on_error;
641
0
    }
642
2.80k
    file_io_handle_opened_in_library = 1;
643
2.80k
  }
644
2.80k
  if( libevtx_file_open_read(
645
2.80k
       internal_file,
646
2.80k
       file_io_handle,
647
2.80k
       error ) != 1 )
648
427
  {
649
427
    libcerror_error_set(
650
427
     error,
651
427
     LIBCERROR_ERROR_DOMAIN_IO,
652
427
     LIBCERROR_IO_ERROR_READ_FAILED,
653
427
     "%s: unable to read from file handle.",
654
427
     function );
655
656
427
    goto on_error;
657
427
  }
658
2.37k
  internal_file->file_io_handle                   = file_io_handle;
659
2.37k
  internal_file->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
660
661
2.37k
  return( 1 );
662
663
427
on_error:
664
427
  if( file_io_handle_opened_in_library != 0 )
665
427
  {
666
427
    libbfio_handle_close(
667
427
     file_io_handle,
668
427
     error );
669
427
  }
670
427
  return( -1 );
671
2.80k
}
672
673
/* Closes a file
674
 * Returns 0 if successful or -1 on error
675
 */
676
int libevtx_file_close(
677
     libevtx_file_t *file,
678
     libcerror_error_t **error )
679
2.37k
{
680
2.37k
  libevtx_internal_file_t *internal_file = NULL;
681
2.37k
  static char *function                  = "libevtx_file_close";
682
2.37k
  int result                             = 0;
683
684
2.37k
  if( file == NULL )
685
0
  {
686
0
    libcerror_error_set(
687
0
     error,
688
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
689
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
690
0
     "%s: invalid file.",
691
0
     function );
692
693
0
    return( -1 );
694
0
  }
695
2.37k
  internal_file = (libevtx_internal_file_t *) file;
696
697
2.37k
  if( internal_file->file_io_handle == NULL )
698
0
  {
699
0
    libcerror_error_set(
700
0
     error,
701
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
702
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
703
0
     "%s: invalid file - missing file IO handle.",
704
0
     function );
705
706
0
    return( -1 );
707
0
  }
708
#if defined( HAVE_DEBUG_OUTPUT )
709
  if( libcnotify_verbose != 0 )
710
  {
711
    if( internal_file->file_io_handle_created_in_library != 0 )
712
    {
713
      if( libevtx_debug_print_read_offsets(
714
           internal_file->file_io_handle,
715
           error ) != 1 )
716
      {
717
        libcerror_error_set(
718
         error,
719
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
720
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
721
         "%s: unable to print the read offsets.",
722
         function );
723
724
        result = -1;
725
      }
726
    }
727
  }
728
#endif
729
2.37k
  if( internal_file->file_io_handle_opened_in_library != 0 )
730
2.37k
  {
731
2.37k
    if( libbfio_handle_close(
732
2.37k
         internal_file->file_io_handle,
733
2.37k
         error ) != 0 )
734
0
    {
735
0
      libcerror_error_set(
736
0
       error,
737
0
       LIBCERROR_ERROR_DOMAIN_IO,
738
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
739
0
       "%s: unable to close file IO handle.",
740
0
       function );
741
742
0
      result = -1;
743
0
    }
744
2.37k
    internal_file->file_io_handle_opened_in_library = 0;
745
2.37k
  }
746
2.37k
  if( internal_file->file_io_handle_created_in_library != 0 )
747
0
  {
748
0
    if( libbfio_handle_free(
749
0
         &( internal_file->file_io_handle ),
750
0
         error ) != 1 )
751
0
    {
752
0
      libcerror_error_set(
753
0
       error,
754
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
755
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
756
0
       "%s: unable to free file IO handle.",
757
0
       function );
758
759
0
      result = -1;
760
0
    }
761
0
    internal_file->file_io_handle_created_in_library = 0;
762
0
  }
763
2.37k
  internal_file->file_io_handle = NULL;
764
765
2.37k
  if( libevtx_io_handle_clear(
766
2.37k
       internal_file->io_handle,
767
2.37k
       error ) != 1 )
768
0
  {
769
0
    libcerror_error_set(
770
0
     error,
771
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
772
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
773
0
     "%s: unable to clear IO handle.",
774
0
     function );
775
776
0
    result = -1;
777
0
  }
778
2.37k
  if( libfdata_list_free(
779
2.37k
       &( internal_file->recovered_records_list ),
780
2.37k
       error ) != 1 )
781
0
  {
782
0
    libcerror_error_set(
783
0
     error,
784
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
785
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
786
0
     "%s: unable to free recovered records list.",
787
0
     function );
788
789
0
    result = -1;
790
0
  }
791
2.37k
  if( libfdata_list_free(
792
2.37k
       &( internal_file->records_list ),
793
2.37k
       error ) != 1 )
794
0
  {
795
0
    libcerror_error_set(
796
0
     error,
797
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
798
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
799
0
     "%s: unable to free records list.",
800
0
     function );
801
802
0
    result = -1;
803
0
  }
804
2.37k
  if( libfcache_cache_free(
805
2.37k
       &( internal_file->records_cache ),
806
2.37k
       error ) != 1 )
807
0
  {
808
0
    libcerror_error_set(
809
0
     error,
810
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
811
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
812
0
     "%s: unable to free records cache.",
813
0
     function );
814
815
0
    result = -1;
816
0
  }
817
2.37k
  if( libfdata_vector_free(
818
2.37k
       &( internal_file->chunks_vector ),
819
2.37k
       error ) != 1 )
820
0
  {
821
0
    libcerror_error_set(
822
0
     error,
823
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
824
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
825
0
     "%s: unable to free chunks vector.",
826
0
     function );
827
828
0
    result = -1;
829
0
  }
830
2.37k
  if( libfcache_cache_free(
831
2.37k
       &( internal_file->chunks_cache ),
832
2.37k
       error ) != 1 )
833
0
  {
834
0
    libcerror_error_set(
835
0
     error,
836
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
837
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
838
0
     "%s: unable to free chunks cache.",
839
0
     function );
840
841
0
    result = -1;
842
0
  }
843
2.37k
  return( result );
844
2.37k
}
845
846
/* Opens a file for reading
847
 * Returns 1 if successful or -1 on error
848
 */
849
int libevtx_file_open_read(
850
     libevtx_internal_file_t *internal_file,
851
     libbfio_handle_t *file_io_handle,
852
     libcerror_error_t **error )
853
2.80k
{
854
2.80k
  libevtx_chunk_t *chunk                 = NULL;
855
2.80k
  libevtx_record_values_t *record_values = NULL;
856
2.80k
  libevtx_chunks_table_t *chunks_table   = NULL;
857
2.80k
  static char *function                  = "libevtx_file_open_read";
858
2.80k
  off64_t file_offset                    = 0;
859
2.80k
  size64_t file_size                     = 0;
860
2.80k
  uint16_t chunk_index                   = 0;
861
2.80k
  uint16_t number_of_chunks              = 0;
862
2.80k
  uint16_t number_of_records             = 0;
863
2.80k
  uint16_t record_index                  = 0;
864
2.80k
  int element_index                      = 0;
865
2.80k
  int result                             = 0;
866
2.80k
  int segment_index                      = 0;
867
868
#if defined( HAVE_VERBOSE_OUTPUT )
869
  uint64_t previous_record_identifier    = 0;
870
#endif
871
#if defined( HAVE_DEBUG_OUTPUT )
872
  uint8_t *trailing_data                 = NULL;
873
  size_t trailing_data_size              = 0;
874
  ssize_t read_count                     = 0;
875
#endif
876
877
2.80k
  if( internal_file == NULL )
878
0
  {
879
0
    libcerror_error_set(
880
0
     error,
881
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
882
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
883
0
     "%s: invalid file.",
884
0
     function );
885
886
0
    return( -1 );
887
0
  }
888
2.80k
  if( internal_file->io_handle == NULL )
889
0
  {
890
0
    libcerror_error_set(
891
0
     error,
892
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
893
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
894
0
     "%s: invalid file - missing IO handle.",
895
0
     function );
896
897
0
    return( -1 );
898
0
  }
899
2.80k
  if( internal_file->chunks_vector != NULL )
900
0
  {
901
0
    libcerror_error_set(
902
0
     error,
903
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
904
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
905
0
     "%s: invalid file - chunks vector already set.",
906
0
     function );
907
908
0
    return( -1 );
909
0
  }
910
2.80k
  if( internal_file->chunks_cache != NULL )
911
0
  {
912
0
    libcerror_error_set(
913
0
     error,
914
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
915
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
916
0
     "%s: invalid file - chunks cache already set.",
917
0
     function );
918
919
0
    return( -1 );
920
0
  }
921
2.80k
  if( internal_file->records_list != NULL )
922
0
  {
923
0
    libcerror_error_set(
924
0
     error,
925
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
926
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
927
0
     "%s: invalid file - records list already set.",
928
0
     function );
929
930
0
    return( -1 );
931
0
  }
932
2.80k
  if( internal_file->recovered_records_list != NULL )
933
0
  {
934
0
    libcerror_error_set(
935
0
     error,
936
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
937
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
938
0
     "%s: invalid file - recovered records list already set.",
939
0
     function );
940
941
0
    return( -1 );
942
0
  }
943
2.80k
  if( internal_file->records_cache != NULL )
944
0
  {
945
0
    libcerror_error_set(
946
0
     error,
947
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
948
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
949
0
     "%s: invalid file - records cache already set.",
950
0
     function );
951
952
0
    return( -1 );
953
0
  }
954
2.80k
  if( libbfio_handle_get_size(
955
2.80k
       file_io_handle,
956
2.80k
       &file_size,
957
2.80k
       error ) != 1 )
958
0
  {
959
0
    libcerror_error_set(
960
0
     error,
961
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
962
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
963
0
     "%s: unable to retrieve file size.",
964
0
     function );
965
966
0
    goto on_error;
967
0
  }
968
#if defined( HAVE_DEBUG_OUTPUT )
969
  if( libcnotify_verbose != 0 )
970
  {
971
    libcnotify_printf(
972
     "Reading file header:\n" );
973
  }
974
#endif
975
2.80k
  if( libevtx_io_handle_read_file_header(
976
2.80k
       internal_file->io_handle,
977
2.80k
       file_io_handle,
978
2.80k
       0,
979
2.80k
       error ) != 1 )
980
187
  {
981
187
    libcerror_error_set(
982
187
     error,
983
187
     LIBCERROR_ERROR_DOMAIN_IO,
984
187
     LIBCERROR_IO_ERROR_READ_FAILED,
985
187
     "%s: unable to read file header.",
986
187
     function );
987
988
187
    goto on_error;
989
187
  }
990
2.61k
  internal_file->io_handle->chunks_data_size = file_size
991
2.61k
                                             - internal_file->io_handle->chunks_data_offset;
992
993
/* TODO clone function ? */
994
2.61k
  if( libfdata_vector_initialize(
995
2.61k
       &( internal_file->chunks_vector ),
996
2.61k
       (size64_t) internal_file->io_handle->chunk_size,
997
2.61k
       (intptr_t *) internal_file->io_handle,
998
2.61k
       NULL,
999
2.61k
       NULL,
1000
2.61k
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_io_handle_read_chunk,
1001
2.61k
       NULL,
1002
2.61k
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
1003
2.61k
       error ) != 1 )
1004
0
  {
1005
0
    libcerror_error_set(
1006
0
     error,
1007
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1008
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1009
0
     "%s: unable to create chunks vector.",
1010
0
     function );
1011
1012
0
    goto on_error;
1013
0
  }
1014
2.61k
  if( libfdata_vector_append_segment(
1015
2.61k
       internal_file->chunks_vector,
1016
2.61k
       &segment_index,
1017
2.61k
       0,
1018
2.61k
       internal_file->io_handle->chunks_data_offset,
1019
2.61k
       internal_file->io_handle->chunks_data_size,
1020
2.61k
       0,
1021
2.61k
       error ) != 1 )
1022
63
  {
1023
63
    libcerror_error_set(
1024
63
     error,
1025
63
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1026
63
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1027
63
     "%s: unable to append segment to chunks vector.",
1028
63
     function );
1029
1030
63
    goto on_error;
1031
63
  }
1032
2.55k
  if( libfcache_cache_initialize(
1033
2.55k
       &( internal_file->chunks_cache ),
1034
2.55k
       LIBEVTX_MAXIMUM_CACHE_ENTRIES_CHUNKS,
1035
2.55k
       error ) != 1 )
1036
0
  {
1037
0
    libcerror_error_set(
1038
0
     error,
1039
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1040
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1041
0
     "%s: unable to create chunks cache.",
1042
0
     function );
1043
1044
0
    goto on_error;
1045
0
  }
1046
#if defined( HAVE_DEBUG_OUTPUT )
1047
  if( libcnotify_verbose != 0 )
1048
  {
1049
    libcnotify_printf(
1050
     "Reading chunks:\n" );
1051
  }
1052
#endif
1053
2.55k
  if( libevtx_chunks_table_initialize(
1054
2.55k
       &chunks_table,
1055
2.55k
       internal_file->io_handle,
1056
2.55k
       internal_file->chunks_vector,
1057
2.55k
       internal_file->chunks_cache,
1058
2.55k
       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 chunks table.",
1065
0
     function );
1066
1067
0
    goto on_error;
1068
0
  }
1069
/* TODO clone function ? */
1070
2.55k
  if( libfdata_list_initialize(
1071
2.55k
       &( internal_file->records_list ),
1072
2.55k
       (intptr_t *) chunks_table,
1073
2.55k
       (int (*)(intptr_t **, libcerror_error_t **)) &libevtx_chunks_table_free,
1074
2.55k
       NULL,
1075
2.55k
       (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfdata_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_chunks_table_read_record,
1076
2.55k
       NULL,
1077
2.55k
       LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
1078
2.55k
       error ) != 1 )
1079
0
  {
1080
0
    libcerror_error_set(
1081
0
     error,
1082
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1083
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1084
0
     "%s: unable to create records list.",
1085
0
     function );
1086
1087
0
    goto on_error;
1088
0
  }
1089
  /* The chunks_table is managed by the list */
1090
1091
2.55k
  if( libfdata_list_initialize(
1092
2.55k
       &( internal_file->recovered_records_list ),
1093
2.55k
       (intptr_t *) chunks_table,
1094
2.55k
       NULL,
1095
2.55k
       NULL,
1096
2.55k
       (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfdata_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_chunks_table_read_record,
1097
2.55k
       NULL,
1098
2.55k
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
1099
2.55k
       error ) != 1 )
1100
0
  {
1101
0
    libcerror_error_set(
1102
0
     error,
1103
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1104
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1105
0
     "%s: unable to create recovered records list.",
1106
0
     function );
1107
1108
0
    chunks_table = NULL;
1109
1110
0
    goto on_error;
1111
0
  }
1112
2.55k
  chunks_table = NULL;
1113
1114
2.55k
  if( libfcache_cache_initialize(
1115
2.55k
       &( internal_file->records_cache ),
1116
2.55k
       LIBEVTX_MAXIMUM_CACHE_ENTRIES_RECORDS,
1117
2.55k
       error ) != 1 )
1118
0
  {
1119
0
    libcerror_error_set(
1120
0
     error,
1121
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1122
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1123
0
     "%s: unable to create records cache.",
1124
0
     function );
1125
1126
0
    goto on_error;
1127
0
  }
1128
2.55k
  file_offset = internal_file->io_handle->chunks_data_offset;
1129
1130
5.99k
  while( ( file_offset + internal_file->io_handle->chunk_size ) <= (off64_t) file_size )
1131
3.61k
  {
1132
3.61k
    if( libevtx_chunk_initialize(
1133
3.61k
         &chunk,
1134
3.61k
         error ) != 1 )
1135
0
    {
1136
0
      libcerror_error_set(
1137
0
       error,
1138
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1139
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1140
0
       "%s: unable to create chunk: %" PRIu16 ".",
1141
0
       function,
1142
0
       chunk_index );
1143
1144
0
      goto on_error;
1145
0
    }
1146
3.61k
    result = libevtx_chunk_read(
1147
3.61k
              chunk,
1148
3.61k
              internal_file->io_handle,
1149
3.61k
              file_io_handle,
1150
3.61k
              file_offset,
1151
3.61k
              error );
1152
1153
3.61k
    if( result == -1 )
1154
177
    {
1155
177
      libcerror_error_set(
1156
177
       error,
1157
177
       LIBCERROR_ERROR_DOMAIN_IO,
1158
177
       LIBCERROR_IO_ERROR_READ_FAILED,
1159
177
       "%s: unable to read chunk: %" PRIu16 ".",
1160
177
       function,
1161
177
       chunk_index );
1162
1163
177
      goto on_error;
1164
177
    }
1165
3.43k
    else if( result == 0 )
1166
203
    {
1167
203
      if( chunk_index < internal_file->io_handle->number_of_chunks )
1168
111
      {
1169
#if defined( HAVE_VERBOSE_OUTPUT )
1170
        if( libcnotify_verbose != 0 )
1171
        {
1172
          libcnotify_printf(
1173
           "%s: corruption detected in chunk: %" PRIu16 ".\n",
1174
           function,
1175
           chunk_index );
1176
        }
1177
#endif
1178
111
        internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED;
1179
111
      }
1180
203
    }
1181
3.23k
    else
1182
3.23k
    {
1183
3.23k
      if( ( chunk->flags & LIBEVTX_CHUNK_FLAG_IS_CORRUPTED ) != 0 )
1184
3.17k
      {
1185
#if defined( HAVE_VERBOSE_OUTPUT )
1186
        if( libcnotify_verbose != 0 )
1187
        {
1188
          libcnotify_printf(
1189
           "%s: corruption detected in chunk: %" PRIu16 ".\n",
1190
           function,
1191
           chunk_index );
1192
        }
1193
#endif
1194
3.17k
        if( chunk_index < internal_file->io_handle->number_of_chunks )
1195
2.40k
        {
1196
2.40k
          internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED;
1197
2.40k
        }
1198
3.17k
      }
1199
3.23k
      if( ( chunk_index < internal_file->io_handle->number_of_chunks )
1200
3.23k
       || ( ( chunk->flags & LIBEVTX_CHUNK_FLAG_IS_CORRUPTED ) == 0 ) )
1201
2.46k
      {
1202
2.46k
        number_of_chunks++;
1203
2.46k
      }
1204
3.23k
      if( libevtx_chunk_get_number_of_records(
1205
3.23k
           chunk,
1206
3.23k
           &number_of_records,
1207
3.23k
           error ) != 1 )
1208
0
      {
1209
0
        libcerror_error_set(
1210
0
         error,
1211
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1212
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1213
0
         "%s: unable to retrieve chunk: %" PRIu16 " number of records.",
1214
0
         function,
1215
0
         chunk_index );
1216
1217
0
        goto on_error;
1218
0
      }
1219
3.23k
      for( record_index = 0;
1220
27.4k
           record_index < number_of_records;
1221
24.2k
           record_index++ )
1222
24.2k
      {
1223
24.2k
        if( libevtx_chunk_get_record(
1224
24.2k
             chunk,
1225
24.2k
             record_index,
1226
24.2k
             &record_values,
1227
24.2k
             error ) != 1 )
1228
0
        {
1229
0
          libcerror_error_set(
1230
0
           error,
1231
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1232
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1233
0
           "%s: unable to retrieve chunk: %" PRIu16 " record: %" PRIu16 ".",
1234
0
           function,
1235
0
           chunk_index,
1236
0
           record_index );
1237
1238
0
          goto on_error;
1239
0
        }
1240
24.2k
        if( record_values == NULL )
1241
0
        {
1242
0
          libcerror_error_set(
1243
0
           error,
1244
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1245
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1246
0
           "%s: missing chunk: %" PRIu16 " record: %" PRIu16 ".",
1247
0
           function,
1248
0
           chunk_index,
1249
0
           record_index );
1250
1251
0
          goto on_error;
1252
0
        }
1253
24.2k
        if( record_values->identifier < internal_file->io_handle->first_record_identifier )
1254
0
        {
1255
0
          internal_file->io_handle->first_record_identifier = record_values->identifier;
1256
0
        }
1257
24.2k
        if( record_values->identifier > internal_file->io_handle->last_record_identifier )
1258
15.9k
        {
1259
15.9k
          internal_file->io_handle->last_record_identifier = record_values->identifier;
1260
15.9k
        }
1261
#if defined( HAVE_VERBOSE_OUTPUT )
1262
        if( ( chunk_index == 0 )
1263
         && ( record_index == 0 ) )
1264
        {
1265
          previous_record_identifier = record_values->identifier;
1266
        }
1267
        else
1268
        {
1269
          previous_record_identifier++;
1270
1271
          if( record_values->identifier != previous_record_identifier )
1272
          {
1273
            if( libcnotify_verbose != 0 )
1274
            {
1275
              libcnotify_printf(
1276
               "%s: detected gap in record identifier ( %" PRIu64 " != %" PRIu64 " ).\n",
1277
               function,
1278
               previous_record_identifier,
1279
               record_values->identifier );
1280
            }
1281
            previous_record_identifier = record_values->identifier;
1282
          }
1283
        }
1284
#endif
1285
        /* The chunk index is stored in the element data size
1286
         */
1287
24.2k
        if( ( chunk_index < internal_file->io_handle->number_of_chunks )
1288
24.2k
         || ( ( internal_file->io_handle->file_flags & LIBEVTX_FILE_FLAG_IS_DIRTY ) != 0 ) )
1289
22.3k
        {
1290
22.3k
          if( libfdata_list_append_element(
1291
22.3k
               internal_file->records_list,
1292
22.3k
               &element_index,
1293
22.3k
               0,
1294
22.3k
               file_offset + record_values->chunk_data_offset,
1295
22.3k
               (size64_t) chunk_index,
1296
22.3k
               0,
1297
22.3k
               error ) != 1 )
1298
0
          {
1299
0
            libcerror_error_set(
1300
0
             error,
1301
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1302
0
             LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1303
0
             "%s: unable to append element to records list.",
1304
0
             function );
1305
1306
0
            goto on_error;
1307
0
          }
1308
22.3k
        }
1309
1.92k
        else
1310
1.92k
        {
1311
          /* If the file is not dirty, records found in chunks outside the indicated
1312
           * range are considered recovered
1313
           */
1314
1.92k
          if( libfdata_list_append_element(
1315
1.92k
               internal_file->recovered_records_list,
1316
1.92k
               &element_index,
1317
1.92k
               0,
1318
1.92k
               file_offset + record_values->chunk_data_offset,
1319
1.92k
               (size64_t) chunk_index,
1320
1.92k
               0,
1321
1.92k
               error ) != 1 )
1322
0
          {
1323
0
            libcerror_error_set(
1324
0
             error,
1325
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1326
0
             LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1327
0
             "%s: unable to append element to recovered records list.",
1328
0
             function );
1329
1330
0
            goto on_error;
1331
0
          }
1332
1.92k
        }
1333
/* TODO cache record values ? */
1334
24.2k
      }
1335
3.23k
      if( libevtx_chunk_get_number_of_recovered_records(
1336
3.23k
           chunk,
1337
3.23k
           &number_of_records,
1338
3.23k
           error ) != 1 )
1339
0
      {
1340
0
        libcerror_error_set(
1341
0
         error,
1342
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1343
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1344
0
         "%s: unable to retrieve chunk: %" PRIu16 " number of recovered records.",
1345
0
         function,
1346
0
         chunk_index );
1347
1348
0
        goto on_error;
1349
0
      }
1350
3.23k
      for( record_index = 0;
1351
88.0k
           record_index < number_of_records;
1352
84.8k
           record_index++ )
1353
84.8k
      {
1354
84.8k
        if( libevtx_chunk_get_recovered_record(
1355
84.8k
             chunk,
1356
84.8k
             record_index,
1357
84.8k
             &record_values,
1358
84.8k
             error ) != 1 )
1359
0
        {
1360
0
          libcerror_error_set(
1361
0
           error,
1362
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1363
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1364
0
           "%s: unable to retrieve chunk: %" PRIu16 " recovered record: %" PRIu16 ".",
1365
0
           function,
1366
0
           chunk_index,
1367
0
           record_index );
1368
1369
0
          goto on_error;
1370
0
        }
1371
84.8k
        if( record_values == NULL )
1372
0
        {
1373
0
          libcerror_error_set(
1374
0
           error,
1375
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1376
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1377
0
           "%s: missing chunk: %" PRIu16 " recovered record: %" PRIu16 ".",
1378
0
           function,
1379
0
           chunk_index,
1380
0
           record_index );
1381
1382
0
          goto on_error;
1383
0
        }
1384
/* TODO check for and remove duplicate identifiers ? */
1385
        /* The chunk index is stored in the element data size
1386
         */
1387
84.8k
        if( libfdata_list_append_element(
1388
84.8k
             internal_file->recovered_records_list,
1389
84.8k
             &element_index,
1390
84.8k
             0,
1391
84.8k
             file_offset + record_values->chunk_data_offset,
1392
84.8k
             (size64_t) chunk_index,
1393
84.8k
             0,
1394
84.8k
             error ) != 1 )
1395
0
        {
1396
0
          libcerror_error_set(
1397
0
           error,
1398
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1399
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1400
0
           "%s: unable to append element to recovered records list.",
1401
0
           function );
1402
1403
0
          goto on_error;
1404
0
        }
1405
84.8k
      }
1406
3.23k
    }
1407
3.43k
    file_offset += chunk->data_size;
1408
1409
3.43k
    if( libevtx_chunk_free(
1410
3.43k
         &chunk,
1411
3.43k
         error ) != 1 )
1412
0
    {
1413
0
      libcerror_error_set(
1414
0
       error,
1415
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1416
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1417
0
       "%s: unable to free chunk: %" PRIu16 ".",
1418
0
       function,
1419
0
       chunk_index );
1420
1421
0
      goto on_error;
1422
0
    }
1423
3.43k
    chunk_index++;
1424
3.43k
  }
1425
2.37k
  internal_file->io_handle->chunks_data_size = file_offset
1426
2.37k
                                             - internal_file->io_handle->chunks_data_offset;
1427
1428
2.37k
  if( number_of_chunks != internal_file->io_handle->number_of_chunks )
1429
1.97k
  {
1430
#if defined( HAVE_VERBOSE_OUTPUT )
1431
    if( libcnotify_verbose != 0 )
1432
    {
1433
      libcnotify_printf(
1434
       "%s: mismatch in number of chunks ( %" PRIu16 " != %" PRIu16 " ).\n",
1435
       function,
1436
       internal_file->io_handle->number_of_chunks,
1437
       chunk_index );
1438
    }
1439
#endif
1440
1.97k
    internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED;
1441
1.97k
  }
1442
#if defined( HAVE_DEBUG_OUTPUT )
1443
  if( libcnotify_verbose != 0 )
1444
  {
1445
    if( file_offset < (off64_t) file_size )
1446
    {
1447
      trailing_data_size = (size_t) ( file_size - file_offset );
1448
1449
      if( trailing_data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
1450
      {
1451
        libcerror_error_set(
1452
         error,
1453
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1454
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1455
         "%s: invalid trailing data size value exceeds maximum allocation size.",
1456
         function );
1457
1458
        goto on_error;
1459
      }
1460
      trailing_data = (uint8_t *) memory_allocate(
1461
                                   sizeof( uint8_t ) * trailing_data_size );
1462
1463
      if( trailing_data == NULL )
1464
      {
1465
        libcerror_error_set(
1466
         error,
1467
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1468
         LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1469
         "%s: unable to create trailing data.",
1470
         function );
1471
1472
        goto on_error;
1473
      }
1474
      read_count = libbfio_handle_read_buffer(
1475
              file_io_handle,
1476
              trailing_data,
1477
              trailing_data_size,
1478
              error );
1479
1480
      if( read_count != (ssize_t) trailing_data_size )
1481
      {
1482
        libcerror_error_set(
1483
         error,
1484
         LIBCERROR_ERROR_DOMAIN_IO,
1485
         LIBCERROR_IO_ERROR_READ_FAILED,
1486
         "%s: unable to read trailing data.",
1487
         function );
1488
1489
        goto on_error;
1490
      }
1491
      file_offset += read_count;
1492
1493
      libcnotify_printf(
1494
       "%s: trailing data:\n",
1495
       function );
1496
      libcnotify_print_data(
1497
       trailing_data,
1498
       trailing_data_size,
1499
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1500
1501
      memory_free(
1502
       trailing_data );
1503
1504
      trailing_data = NULL;
1505
    }
1506
  }
1507
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1508
1509
2.37k
  return( 1 );
1510
1511
427
on_error:
1512
#if defined( HAVE_DEBUG_OUTPUT )
1513
  if( trailing_data != NULL )
1514
  {
1515
    memory_free(
1516
     trailing_data );
1517
  }
1518
#endif
1519
427
  if( chunk != NULL )
1520
177
  {
1521
177
    libevtx_chunk_free(
1522
177
     &chunk,
1523
177
     NULL );
1524
177
  }
1525
427
  if( internal_file->records_cache != NULL )
1526
177
  {
1527
177
    libfcache_cache_free(
1528
177
     &( internal_file->records_cache ),
1529
177
     NULL );
1530
177
  }
1531
427
  if( internal_file->recovered_records_list != NULL )
1532
177
  {
1533
177
    libfdata_list_free(
1534
177
     &( internal_file->recovered_records_list ),
1535
177
     NULL );
1536
177
  }
1537
427
  if( internal_file->records_list != NULL )
1538
177
  {
1539
177
    libfdata_list_free(
1540
177
     &( internal_file->records_list ),
1541
177
     NULL );
1542
177
  }
1543
427
  if( chunks_table != NULL )
1544
0
  {
1545
0
    libevtx_chunks_table_free(
1546
0
     &chunks_table,
1547
0
     NULL );
1548
0
  }
1549
427
  if( internal_file->chunks_cache != NULL )
1550
177
  {
1551
177
    libfcache_cache_free(
1552
177
     &( internal_file->chunks_cache ),
1553
177
     NULL );
1554
177
  }
1555
427
  if( internal_file->chunks_vector != NULL )
1556
240
  {
1557
240
    libfdata_vector_free(
1558
240
     &( internal_file->chunks_vector ),
1559
240
     NULL );
1560
240
  }
1561
427
  return( -1 );
1562
2.55k
}
1563
1564
/* Determine if the file corrupted
1565
 * Returns 1 if corrupted, 0 if not or -1 on error
1566
 */
1567
int libevtx_file_is_corrupted(
1568
     libevtx_file_t *file,
1569
     libcerror_error_t **error )
1570
0
{
1571
0
  libevtx_internal_file_t *internal_file = NULL;
1572
0
  static char *function                  = "libevtx_file_is_corrupted";
1573
1574
0
  if( file == NULL )
1575
0
  {
1576
0
    libcerror_error_set(
1577
0
     error,
1578
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1579
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1580
0
     "%s: invalid file.",
1581
0
     function );
1582
1583
0
    return( -1 );
1584
0
  }
1585
0
  internal_file = (libevtx_internal_file_t *) file;
1586
1587
0
  if( internal_file->io_handle == NULL )
1588
0
  {
1589
0
    libcerror_error_set(
1590
0
     error,
1591
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1592
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1593
0
     "%s: invalid file - missing IO handle.",
1594
0
     function );
1595
1596
0
    return( -1 );
1597
0
  }
1598
0
  if( ( internal_file->io_handle->flags & LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED ) != 0 )
1599
0
  {
1600
0
    return( 1 );
1601
0
  }
1602
0
  return( 0 );
1603
0
}
1604
1605
/* Retrieves the file ASCII codepage
1606
 * Returns 1 if successful or -1 on error
1607
 */
1608
int libevtx_file_get_ascii_codepage(
1609
     libevtx_file_t *file,
1610
     int *ascii_codepage,
1611
     libcerror_error_t **error )
1612
0
{
1613
0
  libevtx_internal_file_t *internal_file = NULL;
1614
0
  static char *function                  = "libevtx_file_get_ascii_codepage";
1615
1616
0
  if( file == NULL )
1617
0
  {
1618
0
    libcerror_error_set(
1619
0
     error,
1620
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1621
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1622
0
     "%s: invalid file.",
1623
0
     function );
1624
1625
0
    return( -1 );
1626
0
  }
1627
0
  internal_file = (libevtx_internal_file_t *) file;
1628
1629
0
  if( internal_file->io_handle == NULL )
1630
0
  {
1631
0
    libcerror_error_set(
1632
0
     error,
1633
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1634
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1635
0
     "%s: invalid file - missing IO handle.",
1636
0
     function );
1637
1638
0
    return( -1 );
1639
0
  }
1640
0
  if( ascii_codepage == NULL )
1641
0
  {
1642
0
    libcerror_error_set(
1643
0
     error,
1644
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1645
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1646
0
     "%s: invalid ASCII codepage.",
1647
0
     function );
1648
1649
0
    return( -1 );
1650
0
  }
1651
0
  *ascii_codepage = internal_file->io_handle->ascii_codepage;
1652
1653
0
  return( 1 );
1654
0
}
1655
1656
/* Sets the file ASCII codepage
1657
 * Returns 1 if successful or -1 on error
1658
 */
1659
int libevtx_file_set_ascii_codepage(
1660
     libevtx_file_t *file,
1661
     int ascii_codepage,
1662
     libcerror_error_t **error )
1663
0
{
1664
0
  libevtx_internal_file_t *internal_file = NULL;
1665
0
  static char *function                  = "libevtx_file_set_ascii_codepage";
1666
1667
0
  if( file == NULL )
1668
0
  {
1669
0
    libcerror_error_set(
1670
0
     error,
1671
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1672
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1673
0
     "%s: invalid file.",
1674
0
     function );
1675
1676
0
    return( -1 );
1677
0
  }
1678
0
  internal_file = (libevtx_internal_file_t *) file;
1679
1680
0
  if( internal_file->io_handle == NULL )
1681
0
  {
1682
0
    libcerror_error_set(
1683
0
     error,
1684
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1685
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1686
0
     "%s: invalid file - missing IO handle.",
1687
0
     function );
1688
1689
0
    return( -1 );
1690
0
  }
1691
0
  if( ( ascii_codepage != LIBEVTX_CODEPAGE_ASCII )
1692
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_874 )
1693
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_932 )
1694
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_936 )
1695
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_949 )
1696
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_950 )
1697
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1250 )
1698
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1251 )
1699
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1252 )
1700
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1253 )
1701
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1254 )
1702
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1255 )
1703
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1256 )
1704
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1257 )
1705
0
   && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1258 ) )
1706
0
  {
1707
0
    libcerror_error_set(
1708
0
     error,
1709
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1710
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1711
0
     "%s: unsupported ASCII codepage.",
1712
0
     function );
1713
1714
0
    return( -1 );
1715
0
  }
1716
0
  internal_file->io_handle->ascii_codepage = ascii_codepage;
1717
1718
0
  return( 1 );
1719
0
}
1720
1721
/* Retrieves the format version
1722
 * Returns 1 if successful or -1 on error
1723
 */
1724
int libevtx_file_get_format_version(
1725
     libevtx_file_t *file,
1726
     uint16_t *major_version,
1727
     uint16_t *minor_version,
1728
     libcerror_error_t **error )
1729
0
{
1730
0
  libevtx_internal_file_t *internal_file = NULL;
1731
0
  static char *function                  = "libevtx_file_get_format_version";
1732
1733
0
  if( file == NULL )
1734
0
  {
1735
0
    libcerror_error_set(
1736
0
     error,
1737
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1738
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1739
0
     "%s: invalid file.",
1740
0
     function );
1741
1742
0
    return( -1 );
1743
0
  }
1744
0
  internal_file = (libevtx_internal_file_t *) file;
1745
1746
0
  if( internal_file->io_handle == NULL )
1747
0
  {
1748
0
    libcerror_error_set(
1749
0
     error,
1750
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1751
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1752
0
     "%s: invalid file - missing IO handle.",
1753
0
     function );
1754
1755
0
    return( -1 );
1756
0
  }
1757
0
  if( major_version == NULL )
1758
0
  {
1759
0
    libcerror_error_set(
1760
0
     error,
1761
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1762
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1763
0
     "%s: invalid major version.",
1764
0
     function );
1765
1766
0
    return( -1 );
1767
0
  }
1768
0
  if( minor_version == NULL )
1769
0
  {
1770
0
    libcerror_error_set(
1771
0
     error,
1772
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1773
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1774
0
     "%s: invalid minor version.",
1775
0
     function );
1776
1777
0
    return( -1 );
1778
0
  }
1779
0
  *major_version = internal_file->io_handle->major_version;
1780
0
  *minor_version = internal_file->io_handle->minor_version;
1781
1782
0
  return( 1 );
1783
0
}
1784
1785
/* Retrieves the file version
1786
 * Returns 1 if successful or -1 on error
1787
 */
1788
int libevtx_file_get_version(
1789
     libevtx_file_t *file,
1790
     uint16_t *major_version,
1791
     uint16_t *minor_version,
1792
     libcerror_error_t **error )
1793
0
{
1794
0
  libevtx_internal_file_t *internal_file = NULL;
1795
0
  static char *function                  = "libevtx_file_get_version";
1796
1797
0
  if( file == NULL )
1798
0
  {
1799
0
    libcerror_error_set(
1800
0
     error,
1801
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1802
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1803
0
     "%s: invalid file.",
1804
0
     function );
1805
1806
0
    return( -1 );
1807
0
  }
1808
0
  internal_file = (libevtx_internal_file_t *) file;
1809
1810
0
  if( internal_file->io_handle == NULL )
1811
0
  {
1812
0
    libcerror_error_set(
1813
0
     error,
1814
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1815
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1816
0
     "%s: invalid file - missing IO handle.",
1817
0
     function );
1818
1819
0
    return( -1 );
1820
0
  }
1821
0
  if( major_version == NULL )
1822
0
  {
1823
0
    libcerror_error_set(
1824
0
     error,
1825
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1826
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1827
0
     "%s: invalid major version.",
1828
0
     function );
1829
1830
0
    return( -1 );
1831
0
  }
1832
0
  if( minor_version == NULL )
1833
0
  {
1834
0
    libcerror_error_set(
1835
0
     error,
1836
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1837
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1838
0
     "%s: invalid minor version.",
1839
0
     function );
1840
1841
0
    return( -1 );
1842
0
  }
1843
0
  *major_version = internal_file->io_handle->major_version;
1844
0
  *minor_version = internal_file->io_handle->minor_version;
1845
1846
0
  return( 1 );
1847
0
}
1848
1849
/* Retrieves the flags
1850
 * Returns 1 if successful or -1 on error
1851
 */
1852
int libevtx_file_get_flags(
1853
     libevtx_file_t *file,
1854
     uint32_t *flags,
1855
     libcerror_error_t **error )
1856
0
{
1857
0
  libevtx_internal_file_t *internal_file = NULL;
1858
0
  static char *function                  = "libevtx_file_get_flags";
1859
1860
0
  if( file == NULL )
1861
0
  {
1862
0
    libcerror_error_set(
1863
0
     error,
1864
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1865
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1866
0
     "%s: invalid file.",
1867
0
     function );
1868
1869
0
    return( -1 );
1870
0
  }
1871
0
  internal_file = (libevtx_internal_file_t *) file;
1872
1873
0
  if( internal_file->io_handle == NULL )
1874
0
  {
1875
0
    libcerror_error_set(
1876
0
     error,
1877
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1878
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1879
0
     "%s: invalid file - missing IO handle.",
1880
0
     function );
1881
1882
0
    return( -1 );
1883
0
  }
1884
0
  if( flags == NULL )
1885
0
  {
1886
0
    libcerror_error_set(
1887
0
     error,
1888
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1889
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1890
0
     "%s: invalid flags.",
1891
0
     function );
1892
1893
0
    return( -1 );
1894
0
  }
1895
0
  *flags = internal_file->io_handle->file_flags;
1896
1897
0
  return( 1 );
1898
0
}
1899
1900
/* Retrieves the number of records
1901
 * Returns 1 if successful or -1 on error
1902
 */
1903
int libevtx_file_get_number_of_records(
1904
     libevtx_file_t *file,
1905
     int *number_of_records,
1906
     libcerror_error_t **error )
1907
1.84k
{
1908
1.84k
  libevtx_internal_file_t *internal_file = NULL;
1909
1.84k
  static char *function                  = "libevtx_file_get_number_of_records";
1910
1911
1.84k
  if( file == NULL )
1912
0
  {
1913
0
    libcerror_error_set(
1914
0
     error,
1915
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1916
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1917
0
     "%s: invalid file.",
1918
0
     function );
1919
1920
0
    return( -1 );
1921
0
  }
1922
1.84k
  internal_file = (libevtx_internal_file_t *) file;
1923
1924
1.84k
  if( libfdata_list_get_number_of_elements(
1925
1.84k
       internal_file->records_list,
1926
1.84k
       number_of_records,
1927
1.84k
       error ) != 1 )
1928
0
  {
1929
0
    libcerror_error_set(
1930
0
     error,
1931
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1932
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1933
0
     "%s: unable to retrieve number of records.",
1934
0
     function );
1935
1936
0
    return( -1 );
1937
0
  }
1938
1.84k
  return( 1 );
1939
1.84k
}
1940
1941
/* Retrieves a specific record
1942
 * Returns 1 if successful or -1 on error
1943
 */
1944
int libevtx_file_get_record(
1945
     libevtx_file_t *file,
1946
     int record_index,
1947
     libevtx_record_t **record,
1948
     libcerror_error_t **error )
1949
0
{
1950
0
  libevtx_internal_file_t *internal_file = NULL;
1951
0
  libevtx_record_values_t *record_values = NULL;
1952
0
  static char *function                  = "libevtx_file_get_record";
1953
1954
0
  if( file == NULL )
1955
0
  {
1956
0
    libcerror_error_set(
1957
0
     error,
1958
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1959
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1960
0
     "%s: invalid file.",
1961
0
     function );
1962
1963
0
    return( -1 );
1964
0
  }
1965
0
  internal_file = (libevtx_internal_file_t *) file;
1966
1967
0
  if( record == NULL )
1968
0
  {
1969
0
    libcerror_error_set(
1970
0
     error,
1971
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1972
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1973
0
     "%s: invalid record.",
1974
0
     function );
1975
1976
0
    return( -1 );
1977
0
  }
1978
0
  if( libfdata_list_get_element_value_by_index(
1979
0
       internal_file->records_list,
1980
0
       (intptr_t *) internal_file->file_io_handle,
1981
0
       (libfdata_cache_t *) internal_file->records_cache,
1982
0
       record_index,
1983
0
       (intptr_t **) &record_values,
1984
0
       0,
1985
0
       error ) != 1 )
1986
0
  {
1987
0
    libcerror_error_set(
1988
0
     error,
1989
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1990
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1991
0
     "%s: unable to retrieve record values: %d.",
1992
0
     function,
1993
0
     record_index );
1994
1995
0
    return( -1 );
1996
0
  }
1997
0
  if( libevtx_record_initialize(
1998
0
       record,
1999
0
       internal_file->io_handle,
2000
0
       internal_file->file_io_handle,
2001
0
       record_values,
2002
0
       LIBEVTX_RECORD_FLAGS_DEFAULT,
2003
0
       error ) != 1 )
2004
0
  {
2005
0
    libcerror_error_set(
2006
0
     error,
2007
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2008
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2009
0
     "%s: unable to create record.",
2010
0
     function );
2011
2012
0
    return( -1 );
2013
0
  }
2014
0
  return( 1 );
2015
0
}
2016
2017
/* Retrieves a specific record
2018
 * Returns 1 if successful or -1 on error
2019
 */
2020
int libevtx_file_get_record_by_index(
2021
     libevtx_file_t *file,
2022
     int record_index,
2023
     libevtx_record_t **record,
2024
     libcerror_error_t **error )
2025
1.50k
{
2026
1.50k
  libevtx_internal_file_t *internal_file = NULL;
2027
1.50k
  libevtx_record_values_t *record_values = NULL;
2028
1.50k
  static char *function                  = "libevtx_file_get_record_by_index";
2029
2030
1.50k
  if( file == NULL )
2031
0
  {
2032
0
    libcerror_error_set(
2033
0
     error,
2034
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2035
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2036
0
     "%s: invalid file.",
2037
0
     function );
2038
2039
0
    return( -1 );
2040
0
  }
2041
1.50k
  internal_file = (libevtx_internal_file_t *) file;
2042
2043
1.50k
  if( record == NULL )
2044
0
  {
2045
0
    libcerror_error_set(
2046
0
     error,
2047
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2048
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2049
0
     "%s: invalid record.",
2050
0
     function );
2051
2052
0
    return( -1 );
2053
0
  }
2054
1.50k
  if( libfdata_list_get_element_value_by_index(
2055
1.50k
       internal_file->records_list,
2056
1.50k
       (intptr_t *) internal_file->file_io_handle,
2057
1.50k
       (libfdata_cache_t *) internal_file->records_cache,
2058
1.50k
       record_index,
2059
1.50k
       (intptr_t **) &record_values,
2060
1.50k
       0,
2061
1.50k
       error ) != 1 )
2062
1.45k
  {
2063
1.45k
    libcerror_error_set(
2064
1.45k
     error,
2065
1.45k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2066
1.45k
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2067
1.45k
     "%s: unable to retrieve record values: %d.",
2068
1.45k
     function,
2069
1.45k
     record_index );
2070
2071
1.45k
    return( -1 );
2072
1.45k
  }
2073
50
  if( libevtx_record_initialize(
2074
50
       record,
2075
50
       internal_file->io_handle,
2076
50
       internal_file->file_io_handle,
2077
50
       record_values,
2078
50
       LIBEVTX_RECORD_FLAGS_DEFAULT,
2079
50
       error ) != 1 )
2080
0
  {
2081
0
    libcerror_error_set(
2082
0
     error,
2083
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2084
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2085
0
     "%s: unable to create record.",
2086
0
     function );
2087
2088
0
    return( -1 );
2089
0
  }
2090
50
  return( 1 );
2091
50
}
2092
2093
/* Retrieves the number of recovered records
2094
 * Returns 1 if successful or -1 on error
2095
 */
2096
int libevtx_file_get_number_of_recovered_records(
2097
     libevtx_file_t *file,
2098
     int *number_of_records,
2099
     libcerror_error_t **error )
2100
0
{
2101
0
  libevtx_internal_file_t *internal_file = NULL;
2102
0
  static char *function                  = "libevtx_file_get_number_of_recovered_records";
2103
2104
0
  if( file == NULL )
2105
0
  {
2106
0
    libcerror_error_set(
2107
0
     error,
2108
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2109
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2110
0
     "%s: invalid file.",
2111
0
     function );
2112
2113
0
    return( -1 );
2114
0
  }
2115
0
  internal_file = (libevtx_internal_file_t *) file;
2116
2117
0
  if( libfdata_list_get_number_of_elements(
2118
0
       internal_file->recovered_records_list,
2119
0
       number_of_records,
2120
0
       error ) != 1 )
2121
0
  {
2122
0
    libcerror_error_set(
2123
0
     error,
2124
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2125
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2126
0
     "%s: unable to retrieve number of records.",
2127
0
     function );
2128
2129
0
    return( -1 );
2130
0
  }
2131
0
  return( 1 );
2132
0
}
2133
2134
/* Retrieves a specific recovered record
2135
 * Returns 1 if successful or -1 on error
2136
 */
2137
int libevtx_file_get_recovered_record(
2138
     libevtx_file_t *file,
2139
     int record_index,
2140
     libevtx_record_t **record,
2141
     libcerror_error_t **error )
2142
0
{
2143
0
  libevtx_internal_file_t *internal_file = NULL;
2144
0
  libevtx_record_values_t *record_values = NULL;
2145
0
  static char *function                  = "libevtx_file_get_recovered_record";
2146
2147
0
  if( file == NULL )
2148
0
  {
2149
0
    libcerror_error_set(
2150
0
     error,
2151
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2152
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2153
0
     "%s: invalid file.",
2154
0
     function );
2155
2156
0
    return( -1 );
2157
0
  }
2158
0
  internal_file = (libevtx_internal_file_t *) file;
2159
2160
0
  if( record == NULL )
2161
0
  {
2162
0
    libcerror_error_set(
2163
0
     error,
2164
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2165
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2166
0
     "%s: invalid record.",
2167
0
     function );
2168
2169
0
    return( -1 );
2170
0
  }
2171
0
  if( libfdata_list_get_element_value_by_index(
2172
0
       internal_file->recovered_records_list,
2173
0
       (intptr_t *) internal_file->file_io_handle,
2174
0
       (libfdata_cache_t *) internal_file->records_cache,
2175
0
       record_index,
2176
0
       (intptr_t **) &record_values,
2177
0
       0,
2178
0
       error ) != 1 )
2179
0
  {
2180
0
    libcerror_error_set(
2181
0
     error,
2182
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2183
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2184
0
     "%s: unable to retrieve record values: %d.",
2185
0
     function,
2186
0
     record_index );
2187
2188
0
    return( -1 );
2189
0
  }
2190
0
  if( libevtx_record_initialize(
2191
0
       record,
2192
0
       internal_file->io_handle,
2193
0
       internal_file->file_io_handle,
2194
0
       record_values,
2195
0
       LIBEVTX_RECORD_FLAGS_DEFAULT,
2196
0
       error ) != 1 )
2197
0
  {
2198
0
    libcerror_error_set(
2199
0
     error,
2200
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2201
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2202
0
     "%s: unable to create record.",
2203
0
     function );
2204
2205
0
    return( -1 );
2206
0
  }
2207
0
  return( 1 );
2208
0
}
2209
2210
/* Retrieves a specific recovered record
2211
 * Returns 1 if successful or -1 on error
2212
 */
2213
int libevtx_file_get_recovered_record_by_index(
2214
     libevtx_file_t *file,
2215
     int record_index,
2216
     libevtx_record_t **record,
2217
     libcerror_error_t **error )
2218
0
{
2219
0
  libevtx_internal_file_t *internal_file = NULL;
2220
0
  libevtx_record_values_t *record_values = NULL;
2221
0
  static char *function                  = "libevtx_file_get_recovered_record_by_index";
2222
2223
0
  if( file == NULL )
2224
0
  {
2225
0
    libcerror_error_set(
2226
0
     error,
2227
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2228
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2229
0
     "%s: invalid file.",
2230
0
     function );
2231
2232
0
    return( -1 );
2233
0
  }
2234
0
  internal_file = (libevtx_internal_file_t *) file;
2235
2236
0
  if( record == NULL )
2237
0
  {
2238
0
    libcerror_error_set(
2239
0
     error,
2240
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2241
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2242
0
     "%s: invalid record.",
2243
0
     function );
2244
2245
0
    return( -1 );
2246
0
  }
2247
0
  if( libfdata_list_get_element_value_by_index(
2248
0
       internal_file->recovered_records_list,
2249
0
       (intptr_t *) internal_file->file_io_handle,
2250
0
       (libfdata_cache_t *) internal_file->records_cache,
2251
0
       record_index,
2252
0
       (intptr_t **) &record_values,
2253
0
       0,
2254
0
       error ) != 1 )
2255
0
  {
2256
0
    libcerror_error_set(
2257
0
     error,
2258
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2259
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2260
0
     "%s: unable to retrieve record values: %d.",
2261
0
     function,
2262
0
     record_index );
2263
2264
0
    return( -1 );
2265
0
  }
2266
0
  if( libevtx_record_initialize(
2267
0
       record,
2268
0
       internal_file->io_handle,
2269
0
       internal_file->file_io_handle,
2270
0
       record_values,
2271
0
       LIBEVTX_RECORD_FLAGS_DEFAULT,
2272
0
       error ) != 1 )
2273
0
  {
2274
0
    libcerror_error_set(
2275
0
     error,
2276
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2277
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2278
0
     "%s: unable to create record.",
2279
0
     function );
2280
2281
0
    return( -1 );
2282
0
  }
2283
0
  return( 1 );
2284
0
}
2285