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