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