1 /*
2  * Python object wrapper of libevt_file_t
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 <narrow_string.h>
24 #include <types.h>
25 
26 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
27 #include <stdlib.h>
28 #endif
29 
30 #include "pyevt_codepage.h"
31 #include "pyevt_error.h"
32 #include "pyevt_file.h"
33 #include "pyevt_file_object_io_handle.h"
34 #include "pyevt_libbfio.h"
35 #include "pyevt_libcerror.h"
36 #include "pyevt_libclocale.h"
37 #include "pyevt_libevt.h"
38 #include "pyevt_python.h"
39 #include "pyevt_record.h"
40 #include "pyevt_records.h"
41 #include "pyevt_unused.h"
42 
43 #if !defined( LIBEVT_HAVE_BFIO )
44 
45 LIBEVT_EXTERN \
46 int libevt_file_open_file_io_handle(
47      libevt_file_t *file,
48      libbfio_handle_t *file_io_handle,
49      int access_flags,
50      libevt_error_t **error );
51 
52 #endif /* !defined( LIBEVT_HAVE_BFIO ) */
53 
54 PyMethodDef pyevt_file_object_methods[] = {
55 
56 	{ "signal_abort",
57 	  (PyCFunction) pyevt_file_signal_abort,
58 	  METH_NOARGS,
59 	  "signal_abort() -> None\n"
60 	  "\n"
61 	  "Signals the file to abort the current activity." },
62 
63 	{ "open",
64 	  (PyCFunction) pyevt_file_open,
65 	  METH_VARARGS | METH_KEYWORDS,
66 	  "open(filename, mode='r') -> None\n"
67 	  "\n"
68 	  "Opens a file." },
69 
70 	{ "open_file_object",
71 	  (PyCFunction) pyevt_file_open_file_object,
72 	  METH_VARARGS | METH_KEYWORDS,
73 	  "open_file_object(file_object, mode='r') -> None\n"
74 	  "\n"
75 	  "Opens a file using a file-like object." },
76 
77 	{ "close",
78 	  (PyCFunction) pyevt_file_close,
79 	  METH_NOARGS,
80 	  "close() -> None\n"
81 	  "\n"
82 	  "Closes a file." },
83 
84 	{ "is_corrupted",
85 	  (PyCFunction) pyevt_file_is_corrupted,
86 	  METH_NOARGS,
87 	  "is_corrupted() -> Boolean\n"
88 	  "\n"
89 	  "Determines if the file is corrupted." },
90 
91 	{ "get_ascii_codepage",
92 	  (PyCFunction) pyevt_file_get_ascii_codepage,
93 	  METH_NOARGS,
94 	  "get_ascii_codepage() -> String\n"
95 	  "\n"
96 	  "Retrieves the codepage for ASCII strings used in the file." },
97 
98 	{ "set_ascii_codepage",
99 	  (PyCFunction) pyevt_file_set_ascii_codepage,
100 	  METH_VARARGS | METH_KEYWORDS,
101 	  "set_ascii_codepage(codepage) -> None\n"
102 	  "\n"
103 	  "Sets the codepage for ASCII strings used in the file.\n"
104 	  "Expects the codepage to be a string containing a Python codec definition." },
105 
106 	{ "get_format_version",
107 	  (PyCFunction) pyevt_file_get_format_version,
108 	  METH_NOARGS,
109 	  "get_format_version() -> Unicode string\n"
110 	  "\n"
111 	  "Retrieves the format version." },
112 
113 	{ "get_number_of_records",
114 	  (PyCFunction) pyevt_file_get_number_of_records,
115 	  METH_NOARGS,
116 	  "get_number_of_records() -> Integer\n"
117 	  "\n"
118 	  "Retrieves the number of records." },
119 
120 	{ "get_record",
121 	  (PyCFunction) pyevt_file_get_record,
122 	  METH_VARARGS | METH_KEYWORDS,
123 	  "get_record(record_index) -> Object\n"
124 	  "\n"
125 	  "Retrieves the record specified by the index." },
126 
127 	{ "get_number_of_recovered_records",
128 	  (PyCFunction) pyevt_file_get_number_of_recovered_records,
129 	  METH_NOARGS,
130 	  "get_number_of_recovered_records() -> Integer\n"
131 	  "\n"
132 	  "Retrieves the number of recovered records." },
133 
134 	{ "get_recovered_record",
135 	  (PyCFunction) pyevt_file_get_recovered_record,
136 	  METH_VARARGS | METH_KEYWORDS,
137 	  "get_recovered_record(record_index) -> Object\n"
138 	  "\n"
139 	  "Retrieves the recovered record specified by the index." },
140 
141 	/* Sentinel */
142 	{ NULL, NULL, 0, NULL }
143 };
144 
145 PyGetSetDef pyevt_file_object_get_set_definitions[] = {
146 
147 	{ "ascii_codepage",
148 	  (getter) pyevt_file_get_ascii_codepage,
149 	  (setter) pyevt_file_set_ascii_codepage_setter,
150 	  "The codepage used for ASCII strings in the file.",
151 	  NULL },
152 
153 	{ "format_version",
154 	  (getter) pyevt_file_get_format_version,
155 	  (setter) 0,
156 	  "The format version.",
157 	  NULL },
158 
159 	{ "number_of_records",
160 	  (getter) pyevt_file_get_number_of_records,
161 	  (setter) 0,
162 	  "The number of records.",
163 	  NULL },
164 
165 	{ "records",
166 	  (getter) pyevt_file_get_records,
167 	  (setter) 0,
168 	  "The records.",
169 	  NULL },
170 
171 	{ "number_of_recovered_records",
172 	  (getter) pyevt_file_get_number_of_recovered_records,
173 	  (setter) 0,
174 	  "The number of recovered records.",
175 	  NULL },
176 
177 	{ "recovered_records",
178 	  (getter) pyevt_file_get_recovered_records,
179 	  (setter) 0,
180 	  "The recovered records.",
181 	  NULL },
182 
183 	/* Sentinel */
184 	{ NULL, NULL, NULL, NULL, NULL }
185 };
186 
187 PyTypeObject pyevt_file_type_object = {
188 	PyVarObject_HEAD_INIT( NULL, 0 )
189 
190 	/* tp_name */
191 	"pyevt.file",
192 	/* tp_basicsize */
193 	sizeof( pyevt_file_t ),
194 	/* tp_itemsize */
195 	0,
196 	/* tp_dealloc */
197 	(destructor) pyevt_file_free,
198 	/* tp_print */
199 	0,
200 	/* tp_getattr */
201 	0,
202 	/* tp_setattr */
203 	0,
204 	/* tp_compare */
205 	0,
206 	/* tp_repr */
207 	0,
208 	/* tp_as_number */
209 	0,
210 	/* tp_as_sequence */
211 	0,
212 	/* tp_as_mapping */
213 	0,
214 	/* tp_hash */
215 	0,
216 	/* tp_call */
217 	0,
218 	/* tp_str */
219 	0,
220 	/* tp_getattro */
221 	0,
222 	/* tp_setattro */
223 	0,
224 	/* tp_as_buffer */
225 	0,
226 	/* tp_flags */
227 	Py_TPFLAGS_DEFAULT,
228 	/* tp_doc */
229 	"pyevt file object (wraps libevt_file_t)",
230 	/* tp_traverse */
231 	0,
232 	/* tp_clear */
233 	0,
234 	/* tp_richcompare */
235 	0,
236 	/* tp_weaklistoffset */
237 	0,
238 	/* tp_iter */
239 	0,
240 	/* tp_iternext */
241 	0,
242 	/* tp_methods */
243 	pyevt_file_object_methods,
244 	/* tp_members */
245 	0,
246 	/* tp_getset */
247 	pyevt_file_object_get_set_definitions,
248 	/* tp_base */
249 	0,
250 	/* tp_dict */
251 	0,
252 	/* tp_descr_get */
253 	0,
254 	/* tp_descr_set */
255 	0,
256 	/* tp_dictoffset */
257 	0,
258 	/* tp_init */
259 	(initproc) pyevt_file_init,
260 	/* tp_alloc */
261 	0,
262 	/* tp_new */
263 	0,
264 	/* tp_free */
265 	0,
266 	/* tp_is_gc */
267 	0,
268 	/* tp_bases */
269 	NULL,
270 	/* tp_mro */
271 	NULL,
272 	/* tp_cache */
273 	NULL,
274 	/* tp_subclasses */
275 	NULL,
276 	/* tp_weaklist */
277 	NULL,
278 	/* tp_del */
279 	0
280 };
281 
282 /* Initializes a file object
283  * Returns 0 if successful or -1 on error
284  */
pyevt_file_init(pyevt_file_t * pyevt_file)285 int pyevt_file_init(
286      pyevt_file_t *pyevt_file )
287 {
288 	libcerror_error_t *error = NULL;
289 	static char *function    = "pyevt_file_init";
290 
291 	if( pyevt_file == NULL )
292 	{
293 		PyErr_Format(
294 		 PyExc_ValueError,
295 		 "%s: invalid file.",
296 		 function );
297 
298 		return( -1 );
299 	}
300 	/* Make sure libevt file is set to NULL
301 	 */
302 	pyevt_file->file           = NULL;
303 	pyevt_file->file_io_handle = NULL;
304 
305 	if( libevt_file_initialize(
306 	     &( pyevt_file->file ),
307 	     &error ) != 1 )
308 	{
309 		pyevt_error_raise(
310 		 error,
311 		 PyExc_MemoryError,
312 		 "%s: unable to initialize file.",
313 		 function );
314 
315 		libcerror_error_free(
316 		 &error );
317 
318 		return( -1 );
319 	}
320 	return( 0 );
321 }
322 
323 /* Frees a file object
324  */
pyevt_file_free(pyevt_file_t * pyevt_file)325 void pyevt_file_free(
326       pyevt_file_t *pyevt_file )
327 {
328 	struct _typeobject *ob_type = NULL;
329 	libcerror_error_t *error    = NULL;
330 	static char *function       = "pyevt_file_free";
331 	int result                  = 0;
332 
333 	if( pyevt_file == NULL )
334 	{
335 		PyErr_Format(
336 		 PyExc_ValueError,
337 		 "%s: invalid file.",
338 		 function );
339 
340 		return;
341 	}
342 	ob_type = Py_TYPE(
343 	           pyevt_file );
344 
345 	if( ob_type == NULL )
346 	{
347 		PyErr_Format(
348 		 PyExc_ValueError,
349 		 "%s: missing ob_type.",
350 		 function );
351 
352 		return;
353 	}
354 	if( ob_type->tp_free == NULL )
355 	{
356 		PyErr_Format(
357 		 PyExc_ValueError,
358 		 "%s: invalid ob_type - missing tp_free.",
359 		 function );
360 
361 		return;
362 	}
363 	if( pyevt_file->file != NULL )
364 	{
365 		Py_BEGIN_ALLOW_THREADS
366 
367 		result = libevt_file_free(
368 		          &( pyevt_file->file ),
369 		          &error );
370 
371 		Py_END_ALLOW_THREADS
372 
373 		if( result != 1 )
374 		{
375 			pyevt_error_raise(
376 			 error,
377 			 PyExc_MemoryError,
378 			 "%s: unable to free libevt file.",
379 			 function );
380 
381 			libcerror_error_free(
382 			 &error );
383 		}
384 	}
385 	ob_type->tp_free(
386 	 (PyObject*) pyevt_file );
387 }
388 
389 /* Signals the file to abort the current activity
390  * Returns a Python object if successful or NULL on error
391  */
pyevt_file_signal_abort(pyevt_file_t * pyevt_file,PyObject * arguments PYEVT_ATTRIBUTE_UNUSED)392 PyObject *pyevt_file_signal_abort(
393            pyevt_file_t *pyevt_file,
394            PyObject *arguments PYEVT_ATTRIBUTE_UNUSED )
395 {
396 	libcerror_error_t *error = NULL;
397 	static char *function    = "pyevt_file_signal_abort";
398 	int result               = 0;
399 
400 	PYEVT_UNREFERENCED_PARAMETER( arguments )
401 
402 	if( pyevt_file == NULL )
403 	{
404 		PyErr_Format(
405 		 PyExc_ValueError,
406 		 "%s: invalid file.",
407 		 function );
408 
409 		return( NULL );
410 	}
411 	Py_BEGIN_ALLOW_THREADS
412 
413 	result = libevt_file_signal_abort(
414 	          pyevt_file->file,
415 	          &error );
416 
417 	Py_END_ALLOW_THREADS
418 
419 	if( result != 1 )
420 	{
421 		pyevt_error_raise(
422 		 error,
423 		 PyExc_IOError,
424 		 "%s: unable to signal abort.",
425 		 function );
426 
427 		libcerror_error_free(
428 		 &error );
429 
430 		return( NULL );
431 	}
432 	Py_IncRef(
433 	 Py_None );
434 
435 	return( Py_None );
436 }
437 
438 /* Opens a file
439  * Returns a Python object if successful or NULL on error
440  */
pyevt_file_open(pyevt_file_t * pyevt_file,PyObject * arguments,PyObject * keywords)441 PyObject *pyevt_file_open(
442            pyevt_file_t *pyevt_file,
443            PyObject *arguments,
444            PyObject *keywords )
445 {
446 	PyObject *string_object      = NULL;
447 	libcerror_error_t *error     = NULL;
448 	const char *filename_narrow  = NULL;
449 	static char *function        = "pyevt_file_open";
450 	static char *keyword_list[]  = { "filename", "mode", NULL };
451 	char *mode                   = NULL;
452 	int result                   = 0;
453 
454 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
455 	const wchar_t *filename_wide = NULL;
456 #else
457 	PyObject *utf8_string_object = NULL;
458 #endif
459 
460 	if( pyevt_file == NULL )
461 	{
462 		PyErr_Format(
463 		 PyExc_ValueError,
464 		 "%s: invalid file.",
465 		 function );
466 
467 		return( NULL );
468 	}
469 	/* Note that PyArg_ParseTupleAndKeywords with "s" will force Unicode strings to be converted to narrow character string.
470 	 * On Windows the narrow character strings contains an extended ASCII string with a codepage. Hence we get a conversion
471 	 * exception. This will also fail if the default encoding is not set correctly. We cannot use "u" here either since that
472 	 * does not allow us to pass non Unicode string objects and Python (at least 2.7) does not seems to automatically upcast them.
473 	 */
474 	if( PyArg_ParseTupleAndKeywords(
475 	     arguments,
476 	     keywords,
477 	     "O|s",
478 	     keyword_list,
479 	     &string_object,
480 	     &mode ) == 0 )
481 	{
482 		return( NULL );
483 	}
484 	if( ( mode != NULL )
485 	 && ( mode[ 0 ] != 'r' ) )
486 	{
487 		PyErr_Format(
488 		 PyExc_ValueError,
489 		 "%s: unsupported mode: %s.",
490 		 function,
491 		 mode );
492 
493 		return( NULL );
494 	}
495 	PyErr_Clear();
496 
497 	result = PyObject_IsInstance(
498 	          string_object,
499 	          (PyObject *) &PyUnicode_Type );
500 
501 	if( result == -1 )
502 	{
503 		pyevt_error_fetch_and_raise(
504 		 PyExc_RuntimeError,
505 		 "%s: unable to determine if string object is of type Unicode.",
506 		 function );
507 
508 		return( NULL );
509 	}
510 	else if( result != 0 )
511 	{
512 		PyErr_Clear();
513 
514 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
515 		filename_wide = (wchar_t *) PyUnicode_AsUnicode(
516 		                             string_object );
517 		Py_BEGIN_ALLOW_THREADS
518 
519 		result = libevt_file_open_wide(
520 		          pyevt_file->file,
521 		          filename_wide,
522 		          LIBEVT_OPEN_READ,
523 		          &error );
524 
525 		Py_END_ALLOW_THREADS
526 #else
527 		utf8_string_object = PyUnicode_AsUTF8String(
528 		                      string_object );
529 
530 		if( utf8_string_object == NULL )
531 		{
532 			pyevt_error_fetch_and_raise(
533 			 PyExc_RuntimeError,
534 			 "%s: unable to convert Unicode string to UTF-8.",
535 			 function );
536 
537 			return( NULL );
538 		}
539 #if PY_MAJOR_VERSION >= 3
540 		filename_narrow = PyBytes_AsString(
541 		                   utf8_string_object );
542 #else
543 		filename_narrow = PyString_AsString(
544 		                   utf8_string_object );
545 #endif
546 		Py_BEGIN_ALLOW_THREADS
547 
548 		result = libevt_file_open(
549 		          pyevt_file->file,
550 		          filename_narrow,
551 		          LIBEVT_OPEN_READ,
552 		          &error );
553 
554 		Py_END_ALLOW_THREADS
555 
556 		Py_DecRef(
557 		 utf8_string_object );
558 #endif
559 		if( result != 1 )
560 		{
561 			pyevt_error_raise(
562 			 error,
563 			 PyExc_IOError,
564 			 "%s: unable to open file.",
565 			 function );
566 
567 			libcerror_error_free(
568 			 &error );
569 
570 			return( NULL );
571 		}
572 		Py_IncRef(
573 		 Py_None );
574 
575 		return( Py_None );
576 	}
577 	PyErr_Clear();
578 
579 #if PY_MAJOR_VERSION >= 3
580 	result = PyObject_IsInstance(
581 	          string_object,
582 	          (PyObject *) &PyBytes_Type );
583 #else
584 	result = PyObject_IsInstance(
585 	          string_object,
586 	          (PyObject *) &PyString_Type );
587 #endif
588 	if( result == -1 )
589 	{
590 		pyevt_error_fetch_and_raise(
591 		 PyExc_RuntimeError,
592 		 "%s: unable to determine if string object is of type string.",
593 		 function );
594 
595 		return( NULL );
596 	}
597 	else if( result != 0 )
598 	{
599 		PyErr_Clear();
600 
601 #if PY_MAJOR_VERSION >= 3
602 		filename_narrow = PyBytes_AsString(
603 		                   string_object );
604 #else
605 		filename_narrow = PyString_AsString(
606 		                   string_object );
607 #endif
608 		Py_BEGIN_ALLOW_THREADS
609 
610 		result = libevt_file_open(
611 		          pyevt_file->file,
612 		          filename_narrow,
613 		          LIBEVT_OPEN_READ,
614 		          &error );
615 
616 		Py_END_ALLOW_THREADS
617 
618 		if( result != 1 )
619 		{
620 			pyevt_error_raise(
621 			 error,
622 			 PyExc_IOError,
623 			 "%s: unable to open file.",
624 			 function );
625 
626 			libcerror_error_free(
627 			 &error );
628 
629 			return( NULL );
630 		}
631 		Py_IncRef(
632 		 Py_None );
633 
634 		return( Py_None );
635 	}
636 	PyErr_Format(
637 	 PyExc_TypeError,
638 	 "%s: unsupported string object type.",
639 	 function );
640 
641 	return( NULL );
642 }
643 
644 /* Opens a file using a file-like object
645  * Returns a Python object if successful or NULL on error
646  */
pyevt_file_open_file_object(pyevt_file_t * pyevt_file,PyObject * arguments,PyObject * keywords)647 PyObject *pyevt_file_open_file_object(
648            pyevt_file_t *pyevt_file,
649            PyObject *arguments,
650            PyObject *keywords )
651 {
652 	PyObject *file_object       = NULL;
653 	libcerror_error_t *error    = NULL;
654 	static char *function       = "pyevt_file_open_file_object";
655 	static char *keyword_list[] = { "file_object", "mode", NULL };
656 	char *mode                  = NULL;
657 	int result                  = 0;
658 
659 	if( pyevt_file == NULL )
660 	{
661 		PyErr_Format(
662 		 PyExc_ValueError,
663 		 "%s: invalid file.",
664 		 function );
665 
666 		return( NULL );
667 	}
668 	if( PyArg_ParseTupleAndKeywords(
669 	     arguments,
670 	     keywords,
671 	     "O|s",
672 	     keyword_list,
673 	     &file_object,
674 	     &mode ) == 0 )
675 	{
676 		return( NULL );
677 	}
678 	if( ( mode != NULL )
679 	 && ( mode[ 0 ] != 'r' ) )
680 	{
681 		PyErr_Format(
682 		 PyExc_ValueError,
683 		 "%s: unsupported mode: %s.",
684 		 function,
685 		 mode );
686 
687 		return( NULL );
688 	}
689 	PyErr_Clear();
690 
691 	result = PyObject_HasAttrString(
692 	          file_object,
693 	          "read" );
694 
695 	if( result != 1 )
696 	{
697 		PyErr_Format(
698 		 PyExc_TypeError,
699 		 "%s: unsupported file object - missing read attribute.",
700 		 function );
701 
702 		return( NULL );
703 	}
704 	PyErr_Clear();
705 
706 	result = PyObject_HasAttrString(
707 	          file_object,
708 	          "seek" );
709 
710 	if( result != 1 )
711 	{
712 		PyErr_Format(
713 		 PyExc_TypeError,
714 		 "%s: unsupported file object - missing seek attribute.",
715 		 function );
716 
717 		return( NULL );
718 	}
719 	if( pyevt_file->file_io_handle != NULL )
720 	{
721 		pyevt_error_raise(
722 		 error,
723 		 PyExc_IOError,
724 		 "%s: invalid file - file IO handle already set.",
725 		 function );
726 
727 		goto on_error;
728 	}
729 	if( pyevt_file_object_initialize(
730 	     &( pyevt_file->file_io_handle ),
731 	     file_object,
732 	     &error ) != 1 )
733 	{
734 		pyevt_error_raise(
735 		 error,
736 		 PyExc_MemoryError,
737 		 "%s: unable to initialize file IO handle.",
738 		 function );
739 
740 		libcerror_error_free(
741 		 &error );
742 
743 		goto on_error;
744 	}
745 	Py_BEGIN_ALLOW_THREADS
746 
747 	result = libevt_file_open_file_io_handle(
748 	          pyevt_file->file,
749 	          pyevt_file->file_io_handle,
750 	          LIBEVT_OPEN_READ,
751 	          &error );
752 
753 	Py_END_ALLOW_THREADS
754 
755 	if( result != 1 )
756 	{
757 		pyevt_error_raise(
758 		 error,
759 		 PyExc_IOError,
760 		 "%s: unable to open file.",
761 		 function );
762 
763 		libcerror_error_free(
764 		 &error );
765 
766 		goto on_error;
767 	}
768 	Py_IncRef(
769 	 Py_None );
770 
771 	return( Py_None );
772 
773 on_error:
774 	if( pyevt_file->file_io_handle != NULL )
775 	{
776 		libbfio_handle_free(
777 		 &( pyevt_file->file_io_handle ),
778 		 NULL );
779 	}
780 	return( NULL );
781 }
782 
783 /* Closes a file
784  * Returns a Python object if successful or NULL on error
785  */
pyevt_file_close(pyevt_file_t * pyevt_file,PyObject * arguments PYEVT_ATTRIBUTE_UNUSED)786 PyObject *pyevt_file_close(
787            pyevt_file_t *pyevt_file,
788            PyObject *arguments PYEVT_ATTRIBUTE_UNUSED )
789 {
790 	libcerror_error_t *error = NULL;
791 	static char *function    = "pyevt_file_close";
792 	int result               = 0;
793 
794 	PYEVT_UNREFERENCED_PARAMETER( arguments )
795 
796 	if( pyevt_file == NULL )
797 	{
798 		PyErr_Format(
799 		 PyExc_ValueError,
800 		 "%s: invalid file.",
801 		 function );
802 
803 		return( NULL );
804 	}
805 	Py_BEGIN_ALLOW_THREADS
806 
807 	result = libevt_file_close(
808 	          pyevt_file->file,
809 	          &error );
810 
811 	Py_END_ALLOW_THREADS
812 
813 	if( result != 0 )
814 	{
815 		pyevt_error_raise(
816 		 error,
817 		 PyExc_IOError,
818 		 "%s: unable to close file.",
819 		 function );
820 
821 		libcerror_error_free(
822 		 &error );
823 
824 		return( NULL );
825 	}
826 	if( pyevt_file->file_io_handle != NULL )
827 	{
828 		Py_BEGIN_ALLOW_THREADS
829 
830 		result = libbfio_handle_free(
831 		          &( pyevt_file->file_io_handle ),
832 		          &error );
833 
834 		Py_END_ALLOW_THREADS
835 
836 		if( result != 1 )
837 		{
838 			pyevt_error_raise(
839 			 error,
840 			 PyExc_MemoryError,
841 			 "%s: unable to free libbfio file IO handle.",
842 			 function );
843 
844 			libcerror_error_free(
845 			 &error );
846 
847 			return( NULL );
848 		}
849 	}
850 	Py_IncRef(
851 	 Py_None );
852 
853 	return( Py_None );
854 }
855 
856 /* Determines if the file is corrupted
857  * Returns a Python object if successful or NULL on error
858  */
pyevt_file_is_corrupted(pyevt_file_t * pyevt_file,PyObject * arguments PYEVT_ATTRIBUTE_UNUSED)859 PyObject *pyevt_file_is_corrupted(
860            pyevt_file_t *pyevt_file,
861            PyObject *arguments PYEVT_ATTRIBUTE_UNUSED )
862 {
863 	libcerror_error_t *error = NULL;
864 	static char *function    = "pyevt_file_is_corrupted";
865 	int result               = 0;
866 
867 	PYEVT_UNREFERENCED_PARAMETER( arguments )
868 
869 	if( pyevt_file == NULL )
870 	{
871 		PyErr_Format(
872 		 PyExc_ValueError,
873 		 "%s: invalid file.",
874 		 function );
875 
876 		return( NULL );
877 	}
878 	Py_BEGIN_ALLOW_THREADS
879 
880 	result = libevt_file_is_corrupted(
881 	          pyevt_file->file,
882 	          &error );
883 
884 	Py_END_ALLOW_THREADS
885 
886 	if( result == -1 )
887 	{
888 		pyevt_error_raise(
889 		 error,
890 		 PyExc_IOError,
891 		 "%s: unable to determine if file is corrupted.",
892 		 function );
893 
894 		libcerror_error_free(
895 		 &error );
896 
897 		return( NULL );
898 	}
899 	if( result != 0 )
900 	{
901 		Py_IncRef(
902 		 (PyObject *) Py_True );
903 
904 		return( Py_True );
905 	}
906 	Py_IncRef(
907 	 (PyObject *) Py_False );
908 
909 	return( Py_False );
910 }
911 
912 /* Retrieves the codepage used for ASCII strings in the file
913  * Returns a Python object if successful or NULL on error
914  */
pyevt_file_get_ascii_codepage(pyevt_file_t * pyevt_file,PyObject * arguments PYEVT_ATTRIBUTE_UNUSED)915 PyObject *pyevt_file_get_ascii_codepage(
916            pyevt_file_t *pyevt_file,
917            PyObject *arguments PYEVT_ATTRIBUTE_UNUSED )
918 {
919 	PyObject *string_object     = NULL;
920 	libcerror_error_t *error    = NULL;
921 	const char *codepage_string = NULL;
922 	static char *function       = "pyevt_file_get_ascii_codepage";
923 	int ascii_codepage          = 0;
924 	int result                  = 0;
925 
926 	PYEVT_UNREFERENCED_PARAMETER( arguments )
927 
928 	if( pyevt_file == NULL )
929 	{
930 		PyErr_Format(
931 		 PyExc_ValueError,
932 		 "%s: invalid file.",
933 		 function );
934 
935 		return( NULL );
936 	}
937 	Py_BEGIN_ALLOW_THREADS
938 
939 	result = libevt_file_get_ascii_codepage(
940 	          pyevt_file->file,
941 	          &ascii_codepage,
942 	          &error );
943 
944 	Py_END_ALLOW_THREADS
945 
946 	if( result != 1 )
947 	{
948 		pyevt_error_raise(
949 		 error,
950 		 PyExc_IOError,
951 		 "%s: unable to retrieve ASCII codepage.",
952 		 function );
953 
954 		libcerror_error_free(
955 		 &error );
956 
957 		return( NULL );
958 	}
959 	codepage_string = pyevt_codepage_to_string(
960 	                   ascii_codepage );
961 
962 	if( codepage_string == NULL )
963 	{
964 		PyErr_Format(
965 		 PyExc_ValueError,
966 		 "%s: unsupported ASCII codepage: %d.",
967 		 function,
968 		 ascii_codepage );
969 
970 		return( NULL );
971 	}
972 #if PY_MAJOR_VERSION >= 3
973 	string_object = PyBytes_FromString(
974 	                 codepage_string );
975 #else
976 	string_object = PyString_FromString(
977 	                 codepage_string );
978 #endif
979 	if( string_object == NULL )
980 	{
981 		PyErr_Format(
982 		 PyExc_IOError,
983 		 "%s: unable to convert codepage string into string object.",
984 		 function );
985 
986 		return( NULL );
987 	}
988 	return( string_object );
989 }
990 
991 /* Sets the codepage used for ASCII strings in the file
992  * Returns 1 if successful or -1 on error
993  */
pyevt_file_set_ascii_codepage_from_string(pyevt_file_t * pyevt_file,const char * codepage_string)994 int pyevt_file_set_ascii_codepage_from_string(
995      pyevt_file_t *pyevt_file,
996      const char *codepage_string )
997 {
998 	libcerror_error_t *error      = NULL;
999 	static char *function         = "pyevt_file_set_ascii_codepage_from_string";
1000 	size_t codepage_string_length = 0;
1001 	uint32_t feature_flags        = 0;
1002 	int ascii_codepage            = 0;
1003 	int result                    = 0;
1004 
1005 	if( pyevt_file == NULL )
1006 	{
1007 		PyErr_Format(
1008 		 PyExc_ValueError,
1009 		 "%s: invalid file.",
1010 		 function );
1011 
1012 		return( -1 );
1013 	}
1014 	if( codepage_string == NULL )
1015 	{
1016 		PyErr_Format(
1017 		 PyExc_ValueError,
1018 		 "%s: invalid codepage string.",
1019 		 function );
1020 
1021 		return( -1 );
1022 	}
1023 	codepage_string_length = narrow_string_length(
1024 	                          codepage_string );
1025 
1026 	feature_flags = LIBCLOCALE_CODEPAGE_FEATURE_FLAG_HAVE_WINDOWS;
1027 
1028 	if( libclocale_codepage_copy_from_string(
1029 	     &ascii_codepage,
1030 	     codepage_string,
1031 	     codepage_string_length,
1032 	     feature_flags,
1033 	     &error ) != 1 )
1034 	{
1035 		pyevt_error_raise(
1036 		 error,
1037 		 PyExc_RuntimeError,
1038 		 "%s: unable to determine ASCII codepage.",
1039 		 function );
1040 
1041 		libcerror_error_free(
1042 		 &error );
1043 
1044 		return( -1 );
1045 	}
1046 	Py_BEGIN_ALLOW_THREADS
1047 
1048 	result = libevt_file_set_ascii_codepage(
1049 	          pyevt_file->file,
1050 	          ascii_codepage,
1051 	          &error );
1052 
1053 	Py_END_ALLOW_THREADS
1054 
1055 	if( result != 1 )
1056 	{
1057 		pyevt_error_raise(
1058 		 error,
1059 		 PyExc_IOError,
1060 		 "%s: unable to set ASCII codepage.",
1061 		 function );
1062 
1063 		libcerror_error_free(
1064 		 &error );
1065 
1066 		return( -1 );
1067 	}
1068 	return( 1 );
1069 }
1070 
1071 /* Sets the codepage used for ASCII strings in the file
1072  * Returns a Python object if successful or NULL on error
1073  */
pyevt_file_set_ascii_codepage(pyevt_file_t * pyevt_file,PyObject * arguments,PyObject * keywords)1074 PyObject *pyevt_file_set_ascii_codepage(
1075            pyevt_file_t *pyevt_file,
1076            PyObject *arguments,
1077            PyObject *keywords )
1078 {
1079 	char *codepage_string       = NULL;
1080 	static char *keyword_list[] = { "codepage", NULL };
1081 	int result                  = 0;
1082 
1083 	if( PyArg_ParseTupleAndKeywords(
1084 	     arguments,
1085 	     keywords,
1086 	     "s",
1087 	     keyword_list,
1088 	     &codepage_string ) == 0 )
1089 	{
1090 		return( NULL );
1091 	}
1092 	result = pyevt_file_set_ascii_codepage_from_string(
1093 	          pyevt_file,
1094 	          codepage_string );
1095 
1096 	if( result != 1 )
1097 	{
1098 		return( NULL );
1099 	}
1100 	Py_IncRef(
1101 	 Py_None );
1102 
1103 	return( Py_None );
1104 }
1105 
1106 /* Sets the codepage used for ASCII strings in the file
1107  * Returns a Python object if successful or NULL on error
1108  */
pyevt_file_set_ascii_codepage_setter(pyevt_file_t * pyevt_file,PyObject * string_object,void * closure PYEVT_ATTRIBUTE_UNUSED)1109 int pyevt_file_set_ascii_codepage_setter(
1110      pyevt_file_t *pyevt_file,
1111      PyObject *string_object,
1112      void *closure PYEVT_ATTRIBUTE_UNUSED )
1113 {
1114 	PyObject *utf8_string_object = NULL;
1115 	char *codepage_string        = NULL;
1116 	static char *function        = "pyevt_file_set_ascii_codepage_setter";
1117 	int result                   = 0;
1118 
1119 	PYEVT_UNREFERENCED_PARAMETER( closure )
1120 
1121 	PyErr_Clear();
1122 
1123 	result = PyObject_IsInstance(
1124 	          string_object,
1125 	          (PyObject *) &PyUnicode_Type );
1126 
1127 	if( result == -1 )
1128 	{
1129 		pyevt_error_fetch_and_raise(
1130 		 PyExc_RuntimeError,
1131 		 "%s: unable to determine if string object is of type Unicode.",
1132 		 function );
1133 
1134 		return( -1 );
1135 	}
1136 	else if( result != 0 )
1137 	{
1138 		/* The codepage string should only contain ASCII characters.
1139 		 */
1140 		utf8_string_object = PyUnicode_AsUTF8String(
1141 		                      string_object );
1142 
1143 		if( utf8_string_object == NULL )
1144 		{
1145 			pyevt_error_fetch_and_raise(
1146 			 PyExc_RuntimeError,
1147 			 "%s: unable to convert Unicode string to UTF-8.",
1148 			 function );
1149 
1150 			return( -1 );
1151 		}
1152 #if PY_MAJOR_VERSION >= 3
1153 		codepage_string = PyBytes_AsString(
1154 		                   utf8_string_object );
1155 #else
1156 		codepage_string = PyString_AsString(
1157 		                   utf8_string_object );
1158 #endif
1159 		if( codepage_string == NULL )
1160 		{
1161 			return( -1 );
1162 		}
1163 		result = pyevt_file_set_ascii_codepage_from_string(
1164 		          pyevt_file,
1165 		          codepage_string );
1166 
1167 		if( result != 1 )
1168 		{
1169 			return( -1 );
1170 		}
1171 		return( 0 );
1172 	}
1173 	PyErr_Clear();
1174 
1175 #if PY_MAJOR_VERSION >= 3
1176 	result = PyObject_IsInstance(
1177 	          string_object,
1178 	          (PyObject *) &PyBytes_Type );
1179 #else
1180 	result = PyObject_IsInstance(
1181 	          string_object,
1182 	          (PyObject *) &PyString_Type );
1183 #endif
1184 	if( result == -1 )
1185 	{
1186 		pyevt_error_fetch_and_raise(
1187 		 PyExc_RuntimeError,
1188 		 "%s: unable to determine if string object is of type string.",
1189 		 function );
1190 
1191 		return( -1 );
1192 	}
1193 	else if( result != 0 )
1194 	{
1195 #if PY_MAJOR_VERSION >= 3
1196 		codepage_string = PyBytes_AsString(
1197 		                   string_object );
1198 #else
1199 		codepage_string = PyString_AsString(
1200 		                   string_object );
1201 #endif
1202 		if( codepage_string == NULL )
1203 		{
1204 			return( -1 );
1205 		}
1206 		result = pyevt_file_set_ascii_codepage_from_string(
1207 		          pyevt_file,
1208 		          codepage_string );
1209 
1210 		if( result != 1 )
1211 		{
1212 			return( -1 );
1213 		}
1214 		return( 0 );
1215 	}
1216 	PyErr_Format(
1217 	 PyExc_TypeError,
1218 	 "%s: unsupported string object type.",
1219 	 function );
1220 
1221 	return( -1 );
1222 }
1223 
1224 /* Retrieves the format version
1225  * Returns a Python object if successful or NULL on error
1226  */
pyevt_file_get_format_version(pyevt_file_t * pyevt_file,PyObject * arguments PYEVT_ATTRIBUTE_UNUSED)1227 PyObject *pyevt_file_get_format_version(
1228            pyevt_file_t *pyevt_file,
1229            PyObject *arguments PYEVT_ATTRIBUTE_UNUSED )
1230 {
1231 	char utf8_string[ 4 ];
1232 
1233 	PyObject *string_object  = NULL;
1234 	libcerror_error_t *error = NULL;
1235 	const char *errors       = NULL;
1236 	static char *function    = "pyevt_file_get_format_version";
1237 	uint32_t major_version   = 0;
1238 	uint32_t minor_version   = 0;
1239 	int result               = 0;
1240 
1241 	PYEVT_UNREFERENCED_PARAMETER( arguments )
1242 
1243 	if( pyevt_file == NULL )
1244 	{
1245 		PyErr_Format(
1246 		 PyExc_ValueError,
1247 		 "%s: invalid file.",
1248 		 function );
1249 
1250 		return( NULL );
1251 	}
1252 	Py_BEGIN_ALLOW_THREADS
1253 
1254 	result = libevt_file_get_format_version(
1255 	          pyevt_file->file,
1256 	          &major_version,
1257 	          &minor_version,
1258 	          &error );
1259 
1260 	Py_END_ALLOW_THREADS
1261 
1262 	if( result != 1 )
1263 	{
1264 		pyevt_error_raise(
1265 		 error,
1266 		 PyExc_IOError,
1267 		 "%s: unable to retrieve format version.",
1268 		 function );
1269 
1270 		libcerror_error_free(
1271 		 &error );
1272 
1273 		return( NULL );
1274 	}
1275 	if( major_version > 9 )
1276 	{
1277 		PyErr_Format(
1278 		 PyExc_ValueError,
1279 		 "%s: major version out of bounds.",
1280 		 function );
1281 
1282 		return( NULL );
1283 	}
1284 	if( minor_version > 9 )
1285 	{
1286 		PyErr_Format(
1287 		 PyExc_ValueError,
1288 		 "%s: minor version out of bounds.",
1289 		 function );
1290 
1291 		return( NULL );
1292 	}
1293 	utf8_string[ 0 ] = '0' + (char) major_version;
1294 	utf8_string[ 1 ] = '.';
1295 	utf8_string[ 2 ] = '0' + (char) minor_version;
1296 	utf8_string[ 3 ] = 0;
1297 
1298 	/* Pass the string length to PyUnicode_DecodeUTF8 otherwise it makes
1299 	 * the end of string character is part of the string.
1300 	 */
1301 	string_object = PyUnicode_DecodeUTF8(
1302 	                 utf8_string,
1303 	                 (Py_ssize_t) 3,
1304 	                 errors );
1305 
1306 	if( string_object == NULL )
1307 	{
1308 		PyErr_Format(
1309 		 PyExc_IOError,
1310 		 "%s: unable to convert UTF-8 string into Unicode object.",
1311 		 function );
1312 
1313 		return( NULL );
1314 	}
1315 	return( string_object );
1316 }
1317 
1318 /* Retrieves the number of records
1319  * Returns a Python object if successful or NULL on error
1320  */
pyevt_file_get_number_of_records(pyevt_file_t * pyevt_file,PyObject * arguments PYEVT_ATTRIBUTE_UNUSED)1321 PyObject *pyevt_file_get_number_of_records(
1322            pyevt_file_t *pyevt_file,
1323            PyObject *arguments PYEVT_ATTRIBUTE_UNUSED )
1324 {
1325 	PyObject *integer_object = NULL;
1326 	libcerror_error_t *error = NULL;
1327 	static char *function    = "pyevt_file_get_number_of_records";
1328 	int number_of_records    = 0;
1329 	int result               = 0;
1330 
1331 	PYEVT_UNREFERENCED_PARAMETER( arguments )
1332 
1333 	if( pyevt_file == NULL )
1334 	{
1335 		PyErr_Format(
1336 		 PyExc_ValueError,
1337 		 "%s: invalid file.",
1338 		 function );
1339 
1340 		return( NULL );
1341 	}
1342 	Py_BEGIN_ALLOW_THREADS
1343 
1344 	result = libevt_file_get_number_of_records(
1345 	          pyevt_file->file,
1346 	          &number_of_records,
1347 	          &error );
1348 
1349 	Py_END_ALLOW_THREADS
1350 
1351 	if( result != 1 )
1352 	{
1353 		pyevt_error_raise(
1354 		 error,
1355 		 PyExc_IOError,
1356 		 "%s: unable to retrieve number of records.",
1357 		 function );
1358 
1359 		libcerror_error_free(
1360 		 &error );
1361 
1362 		return( NULL );
1363 	}
1364 #if PY_MAJOR_VERSION >= 3
1365 	integer_object = PyLong_FromLong(
1366 	                  (long) number_of_records );
1367 #else
1368 	integer_object = PyInt_FromLong(
1369 	                  (long) number_of_records );
1370 #endif
1371 	return( integer_object );
1372 }
1373 
1374 /* Retrieves a specific record by index
1375  * Returns a Python object if successful or NULL on error
1376  */
pyevt_file_get_record_by_index(PyObject * pyevt_file,int record_index)1377 PyObject *pyevt_file_get_record_by_index(
1378            PyObject *pyevt_file,
1379            int record_index )
1380 {
1381 	PyObject *record_object  = NULL;
1382 	libcerror_error_t *error = NULL;
1383 	libevt_record_t *record  = NULL;
1384 	static char *function    = "pyevt_file_get_record_by_index";
1385 	int result               = 0;
1386 
1387 	if( pyevt_file == NULL )
1388 	{
1389 		PyErr_Format(
1390 		 PyExc_ValueError,
1391 		 "%s: invalid file.",
1392 		 function );
1393 
1394 		return( NULL );
1395 	}
1396 	Py_BEGIN_ALLOW_THREADS
1397 
1398 	result = libevt_file_get_record_by_index(
1399 	          ( (pyevt_file_t *) pyevt_file )->file,
1400 	          record_index,
1401 	          &record,
1402 	          &error );
1403 
1404 	Py_END_ALLOW_THREADS
1405 
1406 	if( result != 1 )
1407 	{
1408 		pyevt_error_raise(
1409 		 error,
1410 		 PyExc_IOError,
1411 		 "%s: unable to retrieve record: %d.",
1412 		 function,
1413 		 record_index );
1414 
1415 		libcerror_error_free(
1416 		 &error );
1417 
1418 		goto on_error;
1419 	}
1420 	record_object = pyevt_record_new(
1421 	                 record,
1422 	                 pyevt_file );
1423 
1424 	if( record_object == NULL )
1425 	{
1426 		PyErr_Format(
1427 		 PyExc_MemoryError,
1428 		 "%s: unable to create record object.",
1429 		 function );
1430 
1431 		goto on_error;
1432 	}
1433 	return( record_object );
1434 
1435 on_error:
1436 	if( record != NULL )
1437 	{
1438 		libevt_record_free(
1439 		 &record,
1440 		 NULL );
1441 	}
1442 	return( NULL );
1443 }
1444 
1445 /* Retrieves a specific record
1446  * Returns a Python object if successful or NULL on error
1447  */
pyevt_file_get_record(pyevt_file_t * pyevt_file,PyObject * arguments,PyObject * keywords)1448 PyObject *pyevt_file_get_record(
1449            pyevt_file_t *pyevt_file,
1450            PyObject *arguments,
1451            PyObject *keywords )
1452 {
1453 	PyObject *record_object     = NULL;
1454 	static char *keyword_list[] = { "record_index", NULL };
1455 	int record_index            = 0;
1456 
1457 	if( PyArg_ParseTupleAndKeywords(
1458 	     arguments,
1459 	     keywords,
1460 	     "i",
1461 	     keyword_list,
1462 	     &record_index ) == 0 )
1463 	{
1464 		return( NULL );
1465 	}
1466 	record_object = pyevt_file_get_record_by_index(
1467 	                 (PyObject *) pyevt_file,
1468 	                 record_index );
1469 
1470 	return( record_object );
1471 }
1472 
1473 /* Retrieves a sequence and iterator object for the records
1474  * Returns a Python object if successful or NULL on error
1475  */
pyevt_file_get_records(pyevt_file_t * pyevt_file,PyObject * arguments PYEVT_ATTRIBUTE_UNUSED)1476 PyObject *pyevt_file_get_records(
1477            pyevt_file_t *pyevt_file,
1478            PyObject *arguments PYEVT_ATTRIBUTE_UNUSED )
1479 {
1480 	PyObject *sequence_object = NULL;
1481 	libcerror_error_t *error  = NULL;
1482 	static char *function     = "pyevt_file_get_records";
1483 	int number_of_records     = 0;
1484 	int result                = 0;
1485 
1486 	PYEVT_UNREFERENCED_PARAMETER( arguments )
1487 
1488 	if( pyevt_file == NULL )
1489 	{
1490 		PyErr_Format(
1491 		 PyExc_ValueError,
1492 		 "%s: invalid file.",
1493 		 function );
1494 
1495 		return( NULL );
1496 	}
1497 	Py_BEGIN_ALLOW_THREADS
1498 
1499 	result = libevt_file_get_number_of_records(
1500 	          pyevt_file->file,
1501 	          &number_of_records,
1502 	          &error );
1503 
1504 	Py_END_ALLOW_THREADS
1505 
1506 	if( result != 1 )
1507 	{
1508 		pyevt_error_raise(
1509 		 error,
1510 		 PyExc_IOError,
1511 		 "%s: unable to retrieve number of records.",
1512 		 function );
1513 
1514 		libcerror_error_free(
1515 		 &error );
1516 
1517 		return( NULL );
1518 	}
1519 	sequence_object = pyevt_records_new(
1520 	                   (PyObject *) pyevt_file,
1521 	                   &pyevt_file_get_record_by_index,
1522 	                   number_of_records );
1523 
1524 	if( sequence_object == NULL )
1525 	{
1526 		pyevt_error_raise(
1527 		 error,
1528 		 PyExc_MemoryError,
1529 		 "%s: unable to create sequence object.",
1530 		 function );
1531 
1532 		return( NULL );
1533 	}
1534 	return( sequence_object );
1535 }
1536 
1537 /* Retrieves the number of recovered records
1538  * Returns a Python object if successful or NULL on error
1539  */
pyevt_file_get_number_of_recovered_records(pyevt_file_t * pyevt_file,PyObject * arguments PYEVT_ATTRIBUTE_UNUSED)1540 PyObject *pyevt_file_get_number_of_recovered_records(
1541            pyevt_file_t *pyevt_file,
1542            PyObject *arguments PYEVT_ATTRIBUTE_UNUSED )
1543 {
1544 	PyObject *integer_object = NULL;
1545 	libcerror_error_t *error = NULL;
1546 	static char *function    = "pyevt_file_get_number_of_recovered_records";
1547 	int number_of_records    = 0;
1548 	int result               = 0;
1549 
1550 	PYEVT_UNREFERENCED_PARAMETER( arguments )
1551 
1552 	if( pyevt_file == NULL )
1553 	{
1554 		PyErr_Format(
1555 		 PyExc_ValueError,
1556 		 "%s: invalid file.",
1557 		 function );
1558 
1559 		return( NULL );
1560 	}
1561 	Py_BEGIN_ALLOW_THREADS
1562 
1563 	result = libevt_file_get_number_of_recovered_records(
1564 	          pyevt_file->file,
1565 	          &number_of_records,
1566 	          &error );
1567 
1568 	Py_END_ALLOW_THREADS
1569 
1570 	if( result != 1 )
1571 	{
1572 		pyevt_error_raise(
1573 		 error,
1574 		 PyExc_IOError,
1575 		 "%s: unable to retrieve number of recovered records.",
1576 		 function );
1577 
1578 		libcerror_error_free(
1579 		 &error );
1580 
1581 		return( NULL );
1582 	}
1583 #if PY_MAJOR_VERSION >= 3
1584 	integer_object = PyLong_FromLong(
1585 	                  (long) number_of_records );
1586 #else
1587 	integer_object = PyInt_FromLong(
1588 	                  (long) number_of_records );
1589 #endif
1590 	return( integer_object );
1591 }
1592 
1593 /* Retrieves a specific recovered recovered record by index
1594  * Returns a Python object if successful or NULL on error
1595  */
pyevt_file_get_recovered_record_by_index(PyObject * pyevt_file,int record_index)1596 PyObject *pyevt_file_get_recovered_record_by_index(
1597            PyObject *pyevt_file,
1598            int record_index )
1599 {
1600 	PyObject *record_object  = NULL;
1601 	libcerror_error_t *error = NULL;
1602 	libevt_record_t *record  = NULL;
1603 	static char *function    = "pyevt_file_get_recovered_record_by_index";
1604 	int result               = 0;
1605 
1606 	if( pyevt_file == NULL )
1607 	{
1608 		PyErr_Format(
1609 		 PyExc_ValueError,
1610 		 "%s: invalid file.",
1611 		 function );
1612 
1613 		return( NULL );
1614 	}
1615 	Py_BEGIN_ALLOW_THREADS
1616 
1617 	result = libevt_file_get_recovered_record(
1618 	          ( (pyevt_file_t *) pyevt_file )->file,
1619 	          record_index,
1620 	          &record,
1621 	          &error );
1622 
1623 	Py_END_ALLOW_THREADS
1624 
1625 	if( result != 1 )
1626 	{
1627 		pyevt_error_raise(
1628 		 error,
1629 		 PyExc_IOError,
1630 		 "%s: unable to retrieve recovered recovered record: %d.",
1631 		 function,
1632 		 record_index );
1633 
1634 		libcerror_error_free(
1635 		 &error );
1636 
1637 		goto on_error;
1638 	}
1639 	record_object = pyevt_record_new(
1640 	                 record,
1641 	                 (PyObject *) pyevt_file );
1642 
1643 	if( record_object == NULL )
1644 	{
1645 		PyErr_Format(
1646 		 PyExc_MemoryError,
1647 		 "%s: unable to create recovered record object.",
1648 		 function );
1649 
1650 		goto on_error;
1651 	}
1652 	return( record_object );
1653 
1654 on_error:
1655 	if( record != NULL )
1656 	{
1657 		libevt_record_free(
1658 		 &record,
1659 		 NULL );
1660 	}
1661 	return( NULL );
1662 }
1663 
1664 /* Retrieves a specific recovered recovered record
1665  * Returns a Python object if successful or NULL on error
1666  */
pyevt_file_get_recovered_record(pyevt_file_t * pyevt_file,PyObject * arguments,PyObject * keywords)1667 PyObject *pyevt_file_get_recovered_record(
1668            pyevt_file_t *pyevt_file,
1669            PyObject *arguments,
1670            PyObject *keywords )
1671 {
1672 	PyObject *record_object     = NULL;
1673 	static char *keyword_list[] = { "record_index", NULL };
1674 	int record_index            = 0;
1675 
1676 	if( PyArg_ParseTupleAndKeywords(
1677 	     arguments,
1678 	     keywords,
1679 	     "i",
1680 	     keyword_list,
1681 	     &record_index ) == 0 )
1682 	{
1683 		return( NULL );
1684 	}
1685 	record_object = pyevt_file_get_recovered_record_by_index(
1686 	                 (PyObject *) pyevt_file,
1687 	                 record_index );
1688 
1689 	return( record_object );
1690 }
1691 
1692 /* Retrieves a sequence and iterator object for the recovered records
1693  * Returns a Python object if successful or NULL on error
1694  */
pyevt_file_get_recovered_records(pyevt_file_t * pyevt_file,PyObject * arguments PYEVT_ATTRIBUTE_UNUSED)1695 PyObject *pyevt_file_get_recovered_records(
1696            pyevt_file_t *pyevt_file,
1697            PyObject *arguments PYEVT_ATTRIBUTE_UNUSED )
1698 {
1699 	PyObject *sequence_object = NULL;
1700 	libcerror_error_t *error  = NULL;
1701 	static char *function     = "pyevt_file_get_recovered_records";
1702 	int number_of_records     = 0;
1703 	int result                = 0;
1704 
1705 	PYEVT_UNREFERENCED_PARAMETER( arguments )
1706 
1707 	if( pyevt_file == NULL )
1708 	{
1709 		PyErr_Format(
1710 		 PyExc_ValueError,
1711 		 "%s: invalid file.",
1712 		 function );
1713 
1714 		return( NULL );
1715 	}
1716 	Py_BEGIN_ALLOW_THREADS
1717 
1718 	result = libevt_file_get_number_of_recovered_records(
1719 	          pyevt_file->file,
1720 	          &number_of_records,
1721 	          &error );
1722 
1723 	Py_END_ALLOW_THREADS
1724 
1725 	if( result != 1 )
1726 	{
1727 		pyevt_error_raise(
1728 		 error,
1729 		 PyExc_IOError,
1730 		 "%s: unable to retrieve number of recovered records.",
1731 		 function );
1732 
1733 		libcerror_error_free(
1734 		 &error );
1735 
1736 		return( NULL );
1737 	}
1738 	sequence_object = pyevt_records_new(
1739 	                   (PyObject *) pyevt_file,
1740 	                   &pyevt_file_get_recovered_record_by_index,
1741 	                   number_of_records );
1742 
1743 	if( sequence_object == NULL )
1744 	{
1745 		pyevt_error_raise(
1746 		 error,
1747 		 PyExc_MemoryError,
1748 		 "%s: unable to create sequence object.",
1749 		 function );
1750 
1751 		return( NULL );
1752 	}
1753 	return( sequence_object );
1754 }
1755 
1756