1 /*
2 * Python object definition of the libfsntfs MFT metadata file
3 *
4 * Copyright (C) 2010-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 <types.h>
24
25 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
26 #include <stdlib.h>
27 #endif
28
29 #include "pyfsntfs_error.h"
30 #include "pyfsntfs_file_entry.h"
31 #include "pyfsntfs_file_object_io_handle.h"
32 #include "pyfsntfs_integer.h"
33 #include "pyfsntfs_libbfio.h"
34 #include "pyfsntfs_libcerror.h"
35 #include "pyfsntfs_libfsntfs.h"
36 #include "pyfsntfs_mft_metadata_file.h"
37 #include "pyfsntfs_mft_metadata_file_entries.h"
38 #include "pyfsntfs_python.h"
39 #include "pyfsntfs_unused.h"
40
41 #if !defined( LIBFSNTFS_HAVE_BFIO )
42
43 LIBFSNTFS_EXTERN \
44 int libfsntfs_mft_metadata_file_open_file_io_handle(
45 libfsntfs_mft_metadata_file_t *mft_metadata_file,
46 libbfio_handle_t *file_io_handle,
47 int access_flags,
48 libfsntfs_error_t **error );
49
50 #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */
51
52 PyMethodDef pyfsntfs_mft_metadata_file_object_methods[] = {
53
54 /* Functions to access the MFT metadata file */
55
56 { "open",
57 (PyCFunction) pyfsntfs_mft_metadata_file_open,
58 METH_VARARGS | METH_KEYWORDS,
59 "open(filename, mode='r') -> None\n"
60 "\n"
61 "Opens a MFT metadata file." },
62
63 { "open_file_object",
64 (PyCFunction) pyfsntfs_mft_metadata_file_open_file_object,
65 METH_VARARGS | METH_KEYWORDS,
66 "open_file_object(file_object, mode='r') -> None\n"
67 "\n"
68 "Opens a MFT metadata file using a file-like object." },
69
70 { "close",
71 (PyCFunction) pyfsntfs_mft_metadata_file_close,
72 METH_NOARGS,
73 "close() -> None\n"
74 "\n"
75 "Closes a MFT metadata file." },
76
77 /* Functions to access the MFT metadata file values */
78
79 { "get_volume_name",
80 (PyCFunction) pyfsntfs_mft_metadata_file_get_volume_name,
81 METH_NOARGS,
82 "get_volume_name() -> Unicode string or None\n"
83 "\n"
84 "Retrieves the volume name." },
85
86 /* Functions to access the file entries */
87
88 { "get_number_of_file_entries",
89 (PyCFunction) pyfsntfs_mft_metadata_file_get_number_of_file_entries,
90 METH_NOARGS,
91 "get_number_of_file_entries() -> Integer\n"
92 "\n"
93 "Retrieves the number of file entries." },
94
95 { "get_file_entry",
96 (PyCFunction) pyfsntfs_mft_metadata_file_get_file_entry,
97 METH_VARARGS | METH_KEYWORDS,
98 "get_file_entry(file_entry_index) -> Object\n"
99 "\n"
100 "Retrieves a specific file entry." },
101
102 /* Sentinel */
103 { NULL, NULL, 0, NULL }
104 };
105
106 PyGetSetDef pyfsntfs_mft_metadata_file_object_get_set_definitions[] = {
107
108 { "volume_name",
109 (getter) pyfsntfs_mft_metadata_file_get_volume_name,
110 (setter) 0,
111 "The volume name.",
112 NULL },
113
114 { "number_of_file_entries",
115 (getter) pyfsntfs_mft_metadata_file_get_number_of_file_entries,
116 (setter) 0,
117 "The number of file entries.",
118 NULL },
119
120 { "file_entries",
121 (getter) pyfsntfs_mft_metadata_file_get_file_entries,
122 (setter) 0,
123 "The file entries",
124 NULL },
125
126 /* Sentinel */
127 { NULL, NULL, NULL, NULL, NULL }
128 };
129
130 PyTypeObject pyfsntfs_mft_metadata_file_type_object = {
131 PyVarObject_HEAD_INIT( NULL, 0 )
132
133 /* tp_name */
134 "pyfsntfs.mft_metadata_file",
135 /* tp_basicsize */
136 sizeof( pyfsntfs_mft_metadata_file_t ),
137 /* tp_itemsize */
138 0,
139 /* tp_dealloc */
140 (destructor) pyfsntfs_mft_metadata_file_free,
141 /* tp_print */
142 0,
143 /* tp_getattr */
144 0,
145 /* tp_setattr */
146 0,
147 /* tp_compare */
148 0,
149 /* tp_repr */
150 0,
151 /* tp_as_number */
152 0,
153 /* tp_as_sequence */
154 0,
155 /* tp_as_mapping */
156 0,
157 /* tp_hash */
158 0,
159 /* tp_call */
160 0,
161 /* tp_str */
162 0,
163 /* tp_getattro */
164 0,
165 /* tp_setattro */
166 0,
167 /* tp_as_buffer */
168 0,
169 /* tp_flags */
170 Py_TPFLAGS_DEFAULT,
171 /* tp_doc */
172 "pyfsntfs MFT metadata file object (wraps libfsntfs_mft_metadata_file_t)",
173 /* tp_traverse */
174 0,
175 /* tp_clear */
176 0,
177 /* tp_richcompare */
178 0,
179 /* tp_weaklistoffset */
180 0,
181 /* tp_iter */
182 0,
183 /* tp_iternext */
184 0,
185 /* tp_methods */
186 pyfsntfs_mft_metadata_file_object_methods,
187 /* tp_members */
188 0,
189 /* tp_getset */
190 pyfsntfs_mft_metadata_file_object_get_set_definitions,
191 /* tp_base */
192 0,
193 /* tp_dict */
194 0,
195 /* tp_descr_get */
196 0,
197 /* tp_descr_set */
198 0,
199 /* tp_dictoffset */
200 0,
201 /* tp_init */
202 (initproc) pyfsntfs_mft_metadata_file_init,
203 /* tp_alloc */
204 0,
205 /* tp_new */
206 0,
207 /* tp_free */
208 0,
209 /* tp_is_gc */
210 0,
211 /* tp_bases */
212 NULL,
213 /* tp_mro */
214 NULL,
215 /* tp_cache */
216 NULL,
217 /* tp_subclasses */
218 NULL,
219 /* tp_weaklist */
220 NULL,
221 /* tp_del */
222 0
223 };
224
225 /* Initializes a MFT metadata file object
226 * Returns 0 if successful or -1 on error
227 */
pyfsntfs_mft_metadata_file_init(pyfsntfs_mft_metadata_file_t * pyfsntfs_mft_metadata_file)228 int pyfsntfs_mft_metadata_file_init(
229 pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file )
230 {
231 libcerror_error_t *error = NULL;
232 static char *function = "pyfsntfs_mft_metadata_file_init";
233
234 if( pyfsntfs_mft_metadata_file == NULL )
235 {
236 PyErr_Format(
237 PyExc_ValueError,
238 "%s: invalid MFT metadata file.",
239 function );
240
241 return( -1 );
242 }
243 /* Make sure libfsntfs MFT metadata file is set to NULL
244 */
245 pyfsntfs_mft_metadata_file->mft_metadata_file = NULL;
246 pyfsntfs_mft_metadata_file->file_io_handle = NULL;
247
248 if( libfsntfs_mft_metadata_file_initialize(
249 &( pyfsntfs_mft_metadata_file->mft_metadata_file ),
250 &error ) != 1 )
251 {
252 pyfsntfs_error_raise(
253 error,
254 PyExc_MemoryError,
255 "%s: unable to initialize MFT metadata file.",
256 function );
257
258 libcerror_error_free(
259 &error );
260
261 return( -1 );
262 }
263 return( 0 );
264 }
265
266 /* Frees a MFT metadata file object
267 */
pyfsntfs_mft_metadata_file_free(pyfsntfs_mft_metadata_file_t * pyfsntfs_mft_metadata_file)268 void pyfsntfs_mft_metadata_file_free(
269 pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file )
270 {
271 struct _typeobject *ob_type = NULL;
272 libcerror_error_t *error = NULL;
273 static char *function = "pyfsntfs_mft_metadata_file_free";
274 int result = 0;
275
276 if( pyfsntfs_mft_metadata_file == NULL )
277 {
278 PyErr_Format(
279 PyExc_ValueError,
280 "%s: invalid MFT metadata file.",
281 function );
282
283 return;
284 }
285 ob_type = Py_TYPE(
286 pyfsntfs_mft_metadata_file );
287
288 if( ob_type == NULL )
289 {
290 PyErr_Format(
291 PyExc_ValueError,
292 "%s: missing ob_type.",
293 function );
294
295 return;
296 }
297 if( ob_type->tp_free == NULL )
298 {
299 PyErr_Format(
300 PyExc_ValueError,
301 "%s: invalid ob_type - missing tp_free.",
302 function );
303
304 return;
305 }
306 if( pyfsntfs_mft_metadata_file->mft_metadata_file != NULL )
307 {
308 Py_BEGIN_ALLOW_THREADS
309
310 result = libfsntfs_mft_metadata_file_free(
311 &( pyfsntfs_mft_metadata_file->mft_metadata_file ),
312 &error );
313
314 Py_END_ALLOW_THREADS
315
316 if( result != 1 )
317 {
318 pyfsntfs_error_raise(
319 error,
320 PyExc_MemoryError,
321 "%s: unable to free libfsntfs MFT metadata file.",
322 function );
323
324 libcerror_error_free(
325 &error );
326 }
327 }
328 ob_type->tp_free(
329 (PyObject*) pyfsntfs_mft_metadata_file );
330 }
331
332 /* Opens a MFT metadata file
333 * Returns a Python object if successful or NULL on error
334 */
pyfsntfs_mft_metadata_file_open(pyfsntfs_mft_metadata_file_t * pyfsntfs_mft_metadata_file,PyObject * arguments,PyObject * keywords)335 PyObject *pyfsntfs_mft_metadata_file_open(
336 pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file,
337 PyObject *arguments,
338 PyObject *keywords )
339 {
340 PyObject *string_object = NULL;
341 libcerror_error_t *error = NULL;
342 static char *function = "pyfsntfs_mft_metadata_file_open";
343 static char *keyword_list[] = { "filename", "mode", NULL };
344 const char *filename_narrow = NULL;
345 char *mode = NULL;
346 int result = 0;
347
348 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
349 const wchar_t *filename_wide = NULL;
350 #else
351 PyObject *utf8_string_object = NULL;
352 #endif
353
354 if( pyfsntfs_mft_metadata_file == NULL )
355 {
356 PyErr_Format(
357 PyExc_ValueError,
358 "%s: invalid MFT metadata file.",
359 function );
360
361 return( NULL );
362 }
363 /* Note that PyArg_ParseTupleAndKeywords with "s" will force Unicode strings to be converted to narrow character string.
364 * On Windows the narrow character strings contains an extended ASCII string with a codepage. Hence we get a conversion
365 * exception. This will also fail if the default encoding is not set correctly. We cannot use "u" here either since that
366 * does not allow us to pass non Unicode string objects and Python (at least 2.7) does not seems to automatically upcast them.
367 */
368 if( PyArg_ParseTupleAndKeywords(
369 arguments,
370 keywords,
371 "O|s",
372 keyword_list,
373 &string_object,
374 &mode ) == 0 )
375 {
376 return( NULL );
377 }
378 if( ( mode != NULL )
379 && ( mode[ 0 ] != 'r' ) )
380 {
381 PyErr_Format(
382 PyExc_ValueError,
383 "%s: unsupported mode: %s.",
384 function,
385 mode );
386
387 return( NULL );
388 }
389 PyErr_Clear();
390
391 result = PyObject_IsInstance(
392 string_object,
393 (PyObject *) &PyUnicode_Type );
394
395 if( result == -1 )
396 {
397 pyfsntfs_error_fetch_and_raise(
398 PyExc_RuntimeError,
399 "%s: unable to determine if string object is of type unicode.",
400 function );
401
402 return( NULL );
403 }
404 else if( result != 0 )
405 {
406 PyErr_Clear();
407
408 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
409 filename_wide = (wchar_t *) PyUnicode_AsUnicode(
410 string_object );
411 Py_BEGIN_ALLOW_THREADS
412
413 result = libfsntfs_mft_metadata_file_open_wide(
414 pyfsntfs_mft_metadata_file->mft_metadata_file,
415 filename_wide,
416 LIBFSNTFS_OPEN_READ,
417 &error );
418
419 Py_END_ALLOW_THREADS
420 #else
421 utf8_string_object = PyUnicode_AsUTF8String(
422 string_object );
423
424 if( utf8_string_object == NULL )
425 {
426 pyfsntfs_error_fetch_and_raise(
427 PyExc_RuntimeError,
428 "%s: unable to convert unicode string to UTF-8.",
429 function );
430
431 return( NULL );
432 }
433 #if PY_MAJOR_VERSION >= 3
434 filename_narrow = PyBytes_AsString(
435 utf8_string_object );
436 #else
437 filename_narrow = PyString_AsString(
438 utf8_string_object );
439 #endif
440 Py_BEGIN_ALLOW_THREADS
441
442 result = libfsntfs_mft_metadata_file_open(
443 pyfsntfs_mft_metadata_file->mft_metadata_file,
444 filename_narrow,
445 LIBFSNTFS_OPEN_READ,
446 &error );
447
448 Py_END_ALLOW_THREADS
449
450 Py_DecRef(
451 utf8_string_object );
452 #endif
453 if( result != 1 )
454 {
455 pyfsntfs_error_raise(
456 error,
457 PyExc_IOError,
458 "%s: unable to open MFT metadata file.",
459 function );
460
461 libcerror_error_free(
462 &error );
463
464 return( NULL );
465 }
466 Py_IncRef(
467 Py_None );
468
469 return( Py_None );
470 }
471 PyErr_Clear();
472
473 #if PY_MAJOR_VERSION >= 3
474 result = PyObject_IsInstance(
475 string_object,
476 (PyObject *) &PyBytes_Type );
477 #else
478 result = PyObject_IsInstance(
479 string_object,
480 (PyObject *) &PyString_Type );
481 #endif
482 if( result == -1 )
483 {
484 pyfsntfs_error_fetch_and_raise(
485 PyExc_RuntimeError,
486 "%s: unable to determine if string object is of type string.",
487 function );
488
489 return( NULL );
490 }
491 else if( result != 0 )
492 {
493 PyErr_Clear();
494
495 #if PY_MAJOR_VERSION >= 3
496 filename_narrow = PyBytes_AsString(
497 string_object );
498 #else
499 filename_narrow = PyString_AsString(
500 string_object );
501 #endif
502 Py_BEGIN_ALLOW_THREADS
503
504 result = libfsntfs_mft_metadata_file_open(
505 pyfsntfs_mft_metadata_file->mft_metadata_file,
506 filename_narrow,
507 LIBFSNTFS_OPEN_READ,
508 &error );
509
510 Py_END_ALLOW_THREADS
511
512 if( result != 1 )
513 {
514 pyfsntfs_error_raise(
515 error,
516 PyExc_IOError,
517 "%s: unable to open MFT metadata file.",
518 function );
519
520 libcerror_error_free(
521 &error );
522
523 return( NULL );
524 }
525 Py_IncRef(
526 Py_None );
527
528 return( Py_None );
529 }
530 PyErr_Format(
531 PyExc_TypeError,
532 "%s: unsupported string object type.",
533 function );
534
535 return( NULL );
536 }
537
538 /* Opens a MFT metadata file using a file-like object
539 * Returns a Python object if successful or NULL on error
540 */
pyfsntfs_mft_metadata_file_open_file_object(pyfsntfs_mft_metadata_file_t * pyfsntfs_mft_metadata_file,PyObject * arguments,PyObject * keywords)541 PyObject *pyfsntfs_mft_metadata_file_open_file_object(
542 pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file,
543 PyObject *arguments,
544 PyObject *keywords )
545 {
546 PyObject *file_object = NULL;
547 libcerror_error_t *error = NULL;
548 char *mode = NULL;
549 static char *keyword_list[] = { "file_object", "mode", NULL };
550 static char *function = "pyfsntfs_mft_metadata_file_open_file_object";
551 int result = 0;
552
553 if( pyfsntfs_mft_metadata_file == NULL )
554 {
555 PyErr_Format(
556 PyExc_ValueError,
557 "%s: invalid MFT metadata file.",
558 function );
559
560 return( NULL );
561 }
562 if( PyArg_ParseTupleAndKeywords(
563 arguments,
564 keywords,
565 "O|s",
566 keyword_list,
567 &file_object,
568 &mode ) == 0 )
569 {
570 return( NULL );
571 }
572 if( ( mode != NULL )
573 && ( mode[ 0 ] != 'r' ) )
574 {
575 PyErr_Format(
576 PyExc_ValueError,
577 "%s: unsupported mode: %s.",
578 function,
579 mode );
580
581 return( NULL );
582 }
583 if( pyfsntfs_file_object_initialize(
584 &( pyfsntfs_mft_metadata_file->file_io_handle ),
585 file_object,
586 &error ) != 1 )
587 {
588 pyfsntfs_error_raise(
589 error,
590 PyExc_MemoryError,
591 "%s: unable to initialize file IO handle.",
592 function );
593
594 libcerror_error_free(
595 &error );
596
597 goto on_error;
598 }
599 Py_BEGIN_ALLOW_THREADS
600
601 result = libfsntfs_mft_metadata_file_open_file_io_handle(
602 pyfsntfs_mft_metadata_file->mft_metadata_file,
603 pyfsntfs_mft_metadata_file->file_io_handle,
604 LIBFSNTFS_OPEN_READ,
605 &error );
606
607 Py_END_ALLOW_THREADS
608
609 if( result != 1 )
610 {
611 pyfsntfs_error_raise(
612 error,
613 PyExc_IOError,
614 "%s: unable to open MFT metadata file.",
615 function );
616
617 libcerror_error_free(
618 &error );
619
620 goto on_error;
621 }
622 Py_IncRef(
623 Py_None );
624
625 return( Py_None );
626
627 on_error:
628 if( pyfsntfs_mft_metadata_file->file_io_handle != NULL )
629 {
630 libbfio_handle_free(
631 &( pyfsntfs_mft_metadata_file->file_io_handle ),
632 NULL );
633 }
634 return( NULL );
635 }
636
637 /* Closes a MFT metadata file
638 * Returns a Python object if successful or NULL on error
639 */
pyfsntfs_mft_metadata_file_close(pyfsntfs_mft_metadata_file_t * pyfsntfs_mft_metadata_file,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)640 PyObject *pyfsntfs_mft_metadata_file_close(
641 pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file,
642 PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
643 {
644 libcerror_error_t *error = NULL;
645 static char *function = "pyfsntfs_mft_metadata_file_close";
646 int result = 0;
647
648 PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
649
650 if( pyfsntfs_mft_metadata_file == NULL )
651 {
652 PyErr_Format(
653 PyExc_ValueError,
654 "%s: invalid MFT metadata file.",
655 function );
656
657 return( NULL );
658 }
659 Py_BEGIN_ALLOW_THREADS
660
661 result = libfsntfs_mft_metadata_file_close(
662 pyfsntfs_mft_metadata_file->mft_metadata_file,
663 &error );
664
665 Py_END_ALLOW_THREADS
666
667 if( result != 0 )
668 {
669 pyfsntfs_error_raise(
670 error,
671 PyExc_IOError,
672 "%s: unable to close MFT metadata file.",
673 function );
674
675 libcerror_error_free(
676 &error );
677
678 return( NULL );
679 }
680 if( pyfsntfs_mft_metadata_file->file_io_handle != NULL )
681 {
682 Py_BEGIN_ALLOW_THREADS
683
684 result = libbfio_handle_free(
685 &( pyfsntfs_mft_metadata_file->file_io_handle ),
686 &error );
687
688 Py_END_ALLOW_THREADS
689
690 if( result != 1 )
691 {
692 pyfsntfs_error_raise(
693 error,
694 PyExc_IOError,
695 "%s: unable to free libbfio file IO handle.",
696 function );
697
698 libcerror_error_free(
699 &error );
700
701 return( NULL );
702 }
703 }
704 Py_IncRef(
705 Py_None );
706
707 return( Py_None );
708 }
709
710 /* Retrieves the volume name
711 * Returns a Python object if successful or NULL on error
712 */
pyfsntfs_mft_metadata_file_get_volume_name(pyfsntfs_mft_metadata_file_t * pyfsntfs_mft_metadata_file,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)713 PyObject *pyfsntfs_mft_metadata_file_get_volume_name(
714 pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file,
715 PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
716 {
717 libcerror_error_t *error = NULL;
718 PyObject *string_object = NULL;
719 const char *errors = NULL;
720 uint8_t *volume_name = NULL;
721 static char *function = "pyfsntfs_mft_metadata_file_get_volume_name";
722 size_t volume_name_size = 0;
723 int result = 0;
724
725 PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
726
727 if( pyfsntfs_mft_metadata_file == NULL )
728 {
729 PyErr_Format(
730 PyExc_TypeError,
731 "%s: invalid MFT metadata file.",
732 function );
733
734 return( NULL );
735 }
736 Py_BEGIN_ALLOW_THREADS
737
738 result = libfsntfs_mft_metadata_file_get_utf8_volume_name_size(
739 pyfsntfs_mft_metadata_file->mft_metadata_file,
740 &volume_name_size,
741 &error );
742
743 Py_END_ALLOW_THREADS
744
745 if( result == -1 )
746 {
747 pyfsntfs_error_raise(
748 error,
749 PyExc_IOError,
750 "%s: unable to retrieve volume name size.",
751 function );
752
753 libcerror_error_free(
754 &error );
755
756 goto on_error;
757 }
758 else if( ( result == 0 )
759 || ( volume_name_size == 0 ) )
760 {
761 Py_IncRef(
762 Py_None );
763
764 return( Py_None );
765 }
766 volume_name = (uint8_t *) PyMem_Malloc(
767 sizeof( uint8_t ) * volume_name_size );
768
769 if( volume_name == NULL )
770 {
771 PyErr_Format(
772 PyExc_IOError,
773 "%s: unable to create volume name.",
774 function );
775
776 goto on_error;
777 }
778 Py_BEGIN_ALLOW_THREADS
779
780 result = libfsntfs_mft_metadata_file_get_utf8_volume_name(
781 pyfsntfs_mft_metadata_file->mft_metadata_file,
782 volume_name,
783 volume_name_size,
784 &error );
785
786 Py_END_ALLOW_THREADS
787
788 if( result != 1 )
789 {
790 pyfsntfs_error_raise(
791 error,
792 PyExc_IOError,
793 "%s: unable to retrieve volume name.",
794 function );
795
796 libcerror_error_free(
797 &error );
798
799 goto on_error;
800 }
801 /* Pass the string length to PyUnicode_DecodeUTF8
802 * otherwise it makes the end of string character is part
803 * of the string
804 */
805 string_object = PyUnicode_DecodeUTF8(
806 (char *) volume_name,
807 (Py_ssize_t) volume_name_size - 1,
808 errors );
809
810 PyMem_Free(
811 volume_name );
812
813 return( string_object );
814
815 on_error:
816 if( volume_name != NULL )
817 {
818 PyMem_Free(
819 volume_name );
820 }
821 return( NULL );
822 }
823
824 /* Retrieves the number of file entries
825 * Returns a Python object if successful or NULL on error
826 */
pyfsntfs_mft_metadata_file_get_number_of_file_entries(pyfsntfs_mft_metadata_file_t * pyfsntfs_mft_metadata_file,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)827 PyObject *pyfsntfs_mft_metadata_file_get_number_of_file_entries(
828 pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file,
829 PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
830 {
831 libcerror_error_t *error = NULL;
832 PyObject *integer_object = NULL;
833 static char *function = "pyfsntfs_mft_metadata_file_get_number_of_file_entries";
834 uint64_t number_of_file_entries = 0;
835 int result = 0;
836
837 PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
838
839 if( pyfsntfs_mft_metadata_file == NULL )
840 {
841 PyErr_Format(
842 PyExc_TypeError,
843 "%s: invalid MFT metadata file.",
844 function );
845
846 return( NULL );
847 }
848 Py_BEGIN_ALLOW_THREADS
849
850 result = libfsntfs_mft_metadata_file_get_number_of_file_entries(
851 pyfsntfs_mft_metadata_file->mft_metadata_file,
852 &number_of_file_entries,
853 &error );
854
855 Py_END_ALLOW_THREADS
856
857 if( result != 1 )
858 {
859 pyfsntfs_error_raise(
860 error,
861 PyExc_IOError,
862 "%s: unable to retrieve number of file entries.",
863 function );
864
865 libcerror_error_free(
866 &error );
867
868 return( NULL );
869 }
870 integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
871 number_of_file_entries );
872
873 return( integer_object );
874 }
875
876 /* Retrieves a specific file entry by index
877 * Returns a Python object if successful or NULL on error
878 */
pyfsntfs_mft_metadata_file_get_file_entry_by_index(pyfsntfs_mft_metadata_file_t * pyfsntfs_mft_metadata_file,uint64_t file_entry_index)879 PyObject *pyfsntfs_mft_metadata_file_get_file_entry_by_index(
880 pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file,
881 uint64_t file_entry_index )
882 {
883 libcerror_error_t *error = NULL;
884 libfsntfs_file_entry_t *file_entry = NULL;
885 PyObject *file_entry_object = NULL;
886 static char *function = "pyfsntfs_mft_metadata_file_get_file_entry_by_index";
887 int result = 0;
888
889 if( pyfsntfs_mft_metadata_file == NULL )
890 {
891 PyErr_Format(
892 PyExc_TypeError,
893 "%s: invalid MFT metadata file.",
894 function );
895
896 return( NULL );
897 }
898 Py_BEGIN_ALLOW_THREADS
899
900 result = libfsntfs_mft_metadata_file_get_file_entry_by_index(
901 pyfsntfs_mft_metadata_file->mft_metadata_file,
902 file_entry_index,
903 &file_entry,
904 &error );
905
906 Py_END_ALLOW_THREADS
907
908 if( result != 1 )
909 {
910 pyfsntfs_error_raise(
911 error,
912 PyExc_IOError,
913 "%s: unable to retrieve file entry: %" PRIu64 ".",
914 function,
915 file_entry_index );
916
917 libcerror_error_free(
918 &error );
919
920 goto on_error;
921 }
922 file_entry_object = pyfsntfs_file_entry_new(
923 file_entry,
924 (PyObject *) pyfsntfs_mft_metadata_file );
925
926 if( file_entry_object == NULL )
927 {
928 PyErr_Format(
929 PyExc_MemoryError,
930 "%s: unable to create file entry object.",
931 function );
932
933 goto on_error;
934 }
935 return( file_entry_object );
936
937 on_error:
938 if( file_entry != NULL )
939 {
940 libfsntfs_file_entry_free(
941 &file_entry,
942 NULL );
943 }
944 return( NULL );
945 }
946
947 /* Retrieves a specific file entry
948 * Returns a Python object if successful or NULL on error
949 */
pyfsntfs_mft_metadata_file_get_file_entry(pyfsntfs_mft_metadata_file_t * pyfsntfs_mft_metadata_file,PyObject * arguments,PyObject * keywords)950 PyObject *pyfsntfs_mft_metadata_file_get_file_entry(
951 pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file,
952 PyObject *arguments,
953 PyObject *keywords )
954 {
955 PyObject *file_entry_object = NULL;
956 static char *keyword_list[] = { "file_entry_index", NULL };
957 int file_entry_index = 0;
958
959 if( PyArg_ParseTupleAndKeywords(
960 arguments,
961 keywords,
962 "i",
963 keyword_list,
964 &file_entry_index ) == 0 )
965 {
966 return( NULL );
967 }
968 file_entry_object = pyfsntfs_mft_metadata_file_get_file_entry_by_index(
969 pyfsntfs_mft_metadata_file,
970 file_entry_index );
971
972 return( file_entry_object );
973 }
974
975 /* Retrieves a file entries sequence and iterator object for the MFT metadata file entries
976 * Returns a Python object if successful or NULL on error
977 */
pyfsntfs_mft_metadata_file_get_file_entries(pyfsntfs_mft_metadata_file_t * pyfsntfs_mft_metadata_file,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)978 PyObject *pyfsntfs_mft_metadata_file_get_file_entries(
979 pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file,
980 PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
981 {
982 libcerror_error_t *error = NULL;
983 PyObject *mft_metadata_file_entries_object = NULL;
984 static char *function = "pyfsntfs_mft_metadata_file_get_file_entries";
985 uint64_t number_of_file_entries = 0;
986 int result = 0;
987
988 PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
989
990 if( pyfsntfs_mft_metadata_file == NULL )
991 {
992 PyErr_Format(
993 PyExc_TypeError,
994 "%s: invalid MFT metadata file.",
995 function );
996
997 return( NULL );
998 }
999 Py_BEGIN_ALLOW_THREADS
1000
1001 result = libfsntfs_mft_metadata_file_get_number_of_file_entries(
1002 pyfsntfs_mft_metadata_file->mft_metadata_file,
1003 &number_of_file_entries,
1004 &error );
1005
1006 Py_END_ALLOW_THREADS
1007
1008 if( result != 1 )
1009 {
1010 pyfsntfs_error_raise(
1011 error,
1012 PyExc_IOError,
1013 "%s: unable to retrieve number of file entries.",
1014 function );
1015
1016 libcerror_error_free(
1017 &error );
1018
1019 return( NULL );
1020 }
1021 mft_metadata_file_entries_object = pyfsntfs_mft_metadata_file_entries_new(
1022 pyfsntfs_mft_metadata_file,
1023 &pyfsntfs_mft_metadata_file_get_file_entry_by_index,
1024 number_of_file_entries );
1025
1026 if( mft_metadata_file_entries_object == NULL )
1027 {
1028 PyErr_Format(
1029 PyExc_MemoryError,
1030 "%s: unable to create MFT metadata file entries object.",
1031 function );
1032
1033 return( NULL );
1034 }
1035 return( mft_metadata_file_entries_object );
1036 }
1037
1038