1 /*
2 * Python object wrapper of libfsapfs_container_t
3 *
4 * Copyright (C) 2018-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 "pyfsapfs_container.h"
30 #include "pyfsapfs_error.h"
31 #include "pyfsapfs_file_object_io_handle.h"
32 #include "pyfsapfs_guid.h"
33 #include "pyfsapfs_integer.h"
34 #include "pyfsapfs_libbfio.h"
35 #include "pyfsapfs_libcerror.h"
36 #include "pyfsapfs_libfsapfs.h"
37 #include "pyfsapfs_python.h"
38 #include "pyfsapfs_unused.h"
39 #include "pyfsapfs_volume.h"
40 #include "pyfsapfs_volumes.h"
41
42 #if !defined( LIBFSAPFS_HAVE_BFIO )
43
44 LIBFSAPFS_EXTERN \
45 int libfsapfs_container_open_file_io_handle(
46 libfsapfs_container_t *container,
47 libbfio_handle_t *file_io_handle,
48 int access_flags,
49 libfsapfs_error_t **error );
50
51 #endif /* !defined( LIBFSAPFS_HAVE_BFIO ) */
52
53 PyMethodDef pyfsapfs_container_object_methods[] = {
54
55 { "signal_abort",
56 (PyCFunction) pyfsapfs_container_signal_abort,
57 METH_NOARGS,
58 "signal_abort() -> None\n"
59 "\n"
60 "Signals the container to abort the current activity." },
61
62 { "open",
63 (PyCFunction) pyfsapfs_container_open,
64 METH_VARARGS | METH_KEYWORDS,
65 "open(filename, mode='r') -> None\n"
66 "\n"
67 "Opens a container." },
68
69 { "open_file_object",
70 (PyCFunction) pyfsapfs_container_open_file_object,
71 METH_VARARGS | METH_KEYWORDS,
72 "open_file_object(file_object, mode='r') -> None\n"
73 "\n"
74 "Opens a container using a file-like object." },
75
76 { "close",
77 (PyCFunction) pyfsapfs_container_close,
78 METH_NOARGS,
79 "close() -> None\n"
80 "\n"
81 "Closes a container." },
82
83 { "is_locked",
84 (PyCFunction) pyfsapfs_container_is_locked,
85 METH_NOARGS,
86 "is_locked() -> Boolean or None\n"
87 "\n"
88 "Determines if the container is locked." },
89
90 { "get_size",
91 (PyCFunction) pyfsapfs_container_get_size,
92 METH_NOARGS,
93 "get_size() -> Integer\n"
94 "\n"
95 "Retrieves the size." },
96
97 { "get_identifier",
98 (PyCFunction) pyfsapfs_container_get_identifier,
99 METH_NOARGS,
100 "get_identifier() -> Unicode string\n"
101 "\n"
102 "Retrieves the identifier." },
103
104 { "get_number_of_volumes",
105 (PyCFunction) pyfsapfs_container_get_number_of_volumes,
106 METH_NOARGS,
107 "get_number_of_volumes() -> Integer\n"
108 "\n"
109 "Retrieves the number of volumes." },
110
111 { "get_volume",
112 (PyCFunction) pyfsapfs_container_get_volume,
113 METH_VARARGS | METH_KEYWORDS,
114 "get_volume(volume_index) -> Object\n"
115 "\n"
116 "Retrieves the of volume specified by the index." },
117
118 /* Sentinel */
119 { NULL, NULL, 0, NULL }
120 };
121
122 PyGetSetDef pyfsapfs_container_object_get_set_definitions[] = {
123
124 { "size",
125 (getter) pyfsapfs_container_get_size,
126 (setter) 0,
127 "The size.",
128 NULL },
129
130 { "identifier",
131 (getter) pyfsapfs_container_get_identifier,
132 (setter) 0,
133 "The identifier.",
134 NULL },
135
136 { "number_of_volumes",
137 (getter) pyfsapfs_container_get_number_of_volumes,
138 (setter) 0,
139 "The number of volumes.",
140 NULL },
141
142 { "volumes",
143 (getter) pyfsapfs_container_get_volumes,
144 (setter) 0,
145 "The of volumes.",
146 NULL },
147
148 /* Sentinel */
149 { NULL, NULL, NULL, NULL, NULL }
150 };
151
152 PyTypeObject pyfsapfs_container_type_object = {
153 PyVarObject_HEAD_INIT( NULL, 0 )
154
155 /* tp_name */
156 "pyfsapfs.container",
157 /* tp_basicsize */
158 sizeof( pyfsapfs_container_t ),
159 /* tp_itemsize */
160 0,
161 /* tp_dealloc */
162 (destructor) pyfsapfs_container_free,
163 /* tp_print */
164 0,
165 /* tp_getattr */
166 0,
167 /* tp_setattr */
168 0,
169 /* tp_compare */
170 0,
171 /* tp_repr */
172 0,
173 /* tp_as_number */
174 0,
175 /* tp_as_sequence */
176 0,
177 /* tp_as_mapping */
178 0,
179 /* tp_hash */
180 0,
181 /* tp_call */
182 0,
183 /* tp_str */
184 0,
185 /* tp_getattro */
186 0,
187 /* tp_setattro */
188 0,
189 /* tp_as_buffer */
190 0,
191 /* tp_flags */
192 Py_TPFLAGS_DEFAULT,
193 /* tp_doc */
194 "pyfsapfs container object (wraps libfsapfs_container_t)",
195 /* tp_traverse */
196 0,
197 /* tp_clear */
198 0,
199 /* tp_richcompare */
200 0,
201 /* tp_weaklistoffset */
202 0,
203 /* tp_iter */
204 0,
205 /* tp_iternext */
206 0,
207 /* tp_methods */
208 pyfsapfs_container_object_methods,
209 /* tp_members */
210 0,
211 /* tp_getset */
212 pyfsapfs_container_object_get_set_definitions,
213 /* tp_base */
214 0,
215 /* tp_dict */
216 0,
217 /* tp_descr_get */
218 0,
219 /* tp_descr_set */
220 0,
221 /* tp_dictoffset */
222 0,
223 /* tp_init */
224 (initproc) pyfsapfs_container_init,
225 /* tp_alloc */
226 0,
227 /* tp_new */
228 0,
229 /* tp_free */
230 0,
231 /* tp_is_gc */
232 0,
233 /* tp_bases */
234 NULL,
235 /* tp_mro */
236 NULL,
237 /* tp_cache */
238 NULL,
239 /* tp_subclasses */
240 NULL,
241 /* tp_weaklist */
242 NULL,
243 /* tp_del */
244 0
245 };
246
247 /* Initializes a container object
248 * Returns 0 if successful or -1 on error
249 */
pyfsapfs_container_init(pyfsapfs_container_t * pyfsapfs_container)250 int pyfsapfs_container_init(
251 pyfsapfs_container_t *pyfsapfs_container )
252 {
253 libcerror_error_t *error = NULL;
254 static char *function = "pyfsapfs_container_init";
255
256 if( pyfsapfs_container == NULL )
257 {
258 PyErr_Format(
259 PyExc_ValueError,
260 "%s: invalid container.",
261 function );
262
263 return( -1 );
264 }
265 /* Make sure libfsapfs container is set to NULL
266 */
267 pyfsapfs_container->container = NULL;
268 pyfsapfs_container->file_io_handle = NULL;
269
270 if( libfsapfs_container_initialize(
271 &( pyfsapfs_container->container ),
272 &error ) != 1 )
273 {
274 pyfsapfs_error_raise(
275 error,
276 PyExc_MemoryError,
277 "%s: unable to initialize container.",
278 function );
279
280 libcerror_error_free(
281 &error );
282
283 return( -1 );
284 }
285 return( 0 );
286 }
287
288 /* Frees a container object
289 */
pyfsapfs_container_free(pyfsapfs_container_t * pyfsapfs_container)290 void pyfsapfs_container_free(
291 pyfsapfs_container_t *pyfsapfs_container )
292 {
293 struct _typeobject *ob_type = NULL;
294 libcerror_error_t *error = NULL;
295 static char *function = "pyfsapfs_container_free";
296 int result = 0;
297
298 if( pyfsapfs_container == NULL )
299 {
300 PyErr_Format(
301 PyExc_ValueError,
302 "%s: invalid container.",
303 function );
304
305 return;
306 }
307 ob_type = Py_TYPE(
308 pyfsapfs_container );
309
310 if( ob_type == NULL )
311 {
312 PyErr_Format(
313 PyExc_ValueError,
314 "%s: missing ob_type.",
315 function );
316
317 return;
318 }
319 if( ob_type->tp_free == NULL )
320 {
321 PyErr_Format(
322 PyExc_ValueError,
323 "%s: invalid ob_type - missing tp_free.",
324 function );
325
326 return;
327 }
328 if( pyfsapfs_container->container != NULL )
329 {
330 Py_BEGIN_ALLOW_THREADS
331
332 result = libfsapfs_container_free(
333 &( pyfsapfs_container->container ),
334 &error );
335
336 Py_END_ALLOW_THREADS
337
338 if( result != 1 )
339 {
340 pyfsapfs_error_raise(
341 error,
342 PyExc_MemoryError,
343 "%s: unable to free libfsapfs container.",
344 function );
345
346 libcerror_error_free(
347 &error );
348 }
349 }
350 ob_type->tp_free(
351 (PyObject*) pyfsapfs_container );
352 }
353
354 /* Signals the container to abort the current activity
355 * Returns a Python object if successful or NULL on error
356 */
pyfsapfs_container_signal_abort(pyfsapfs_container_t * pyfsapfs_container,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)357 PyObject *pyfsapfs_container_signal_abort(
358 pyfsapfs_container_t *pyfsapfs_container,
359 PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
360 {
361 libcerror_error_t *error = NULL;
362 static char *function = "pyfsapfs_container_signal_abort";
363 int result = 0;
364
365 PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
366
367 if( pyfsapfs_container == NULL )
368 {
369 PyErr_Format(
370 PyExc_ValueError,
371 "%s: invalid container.",
372 function );
373
374 return( NULL );
375 }
376 Py_BEGIN_ALLOW_THREADS
377
378 result = libfsapfs_container_signal_abort(
379 pyfsapfs_container->container,
380 &error );
381
382 Py_END_ALLOW_THREADS
383
384 if( result != 1 )
385 {
386 pyfsapfs_error_raise(
387 error,
388 PyExc_IOError,
389 "%s: unable to signal abort.",
390 function );
391
392 libcerror_error_free(
393 &error );
394
395 return( NULL );
396 }
397 Py_IncRef(
398 Py_None );
399
400 return( Py_None );
401 }
402
403 /* Opens a container
404 * Returns a Python object if successful or NULL on error
405 */
pyfsapfs_container_open(pyfsapfs_container_t * pyfsapfs_container,PyObject * arguments,PyObject * keywords)406 PyObject *pyfsapfs_container_open(
407 pyfsapfs_container_t *pyfsapfs_container,
408 PyObject *arguments,
409 PyObject *keywords )
410 {
411 PyObject *string_object = NULL;
412 libcerror_error_t *error = NULL;
413 const char *filename_narrow = NULL;
414 static char *function = "pyfsapfs_container_open";
415 static char *keyword_list[] = { "filename", "mode", NULL };
416 char *mode = NULL;
417 int result = 0;
418
419 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
420 const wchar_t *filename_wide = NULL;
421 #else
422 PyObject *utf8_string_object = NULL;
423 #endif
424
425 if( pyfsapfs_container == NULL )
426 {
427 PyErr_Format(
428 PyExc_ValueError,
429 "%s: invalid container.",
430 function );
431
432 return( NULL );
433 }
434 /* Note that PyArg_ParseTupleAndKeywords with "s" will force Unicode strings to be converted to narrow character string.
435 * On Windows the narrow character strings contains an extended ASCII string with a codepage. Hence we get a conversion
436 * exception. This will also fail if the default encoding is not set correctly. We cannot use "u" here either since that
437 * does not allow us to pass non Unicode string objects and Python (at least 2.7) does not seems to automatically upcast them.
438 */
439 if( PyArg_ParseTupleAndKeywords(
440 arguments,
441 keywords,
442 "O|s",
443 keyword_list,
444 &string_object,
445 &mode ) == 0 )
446 {
447 return( NULL );
448 }
449 if( ( mode != NULL )
450 && ( mode[ 0 ] != 'r' ) )
451 {
452 PyErr_Format(
453 PyExc_ValueError,
454 "%s: unsupported mode: %s.",
455 function,
456 mode );
457
458 return( NULL );
459 }
460 PyErr_Clear();
461
462 result = PyObject_IsInstance(
463 string_object,
464 (PyObject *) &PyUnicode_Type );
465
466 if( result == -1 )
467 {
468 pyfsapfs_error_fetch_and_raise(
469 PyExc_RuntimeError,
470 "%s: unable to determine if string object is of type Unicode.",
471 function );
472
473 return( NULL );
474 }
475 else if( result != 0 )
476 {
477 PyErr_Clear();
478
479 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
480 filename_wide = (wchar_t *) PyUnicode_AsUnicode(
481 string_object );
482 Py_BEGIN_ALLOW_THREADS
483
484 result = libfsapfs_container_open_wide(
485 pyfsapfs_container->container,
486 filename_wide,
487 LIBFSAPFS_OPEN_READ,
488 &error );
489
490 Py_END_ALLOW_THREADS
491 #else
492 utf8_string_object = PyUnicode_AsUTF8String(
493 string_object );
494
495 if( utf8_string_object == NULL )
496 {
497 pyfsapfs_error_fetch_and_raise(
498 PyExc_RuntimeError,
499 "%s: unable to convert Unicode string to UTF-8.",
500 function );
501
502 return( NULL );
503 }
504 #if PY_MAJOR_VERSION >= 3
505 filename_narrow = PyBytes_AsString(
506 utf8_string_object );
507 #else
508 filename_narrow = PyString_AsString(
509 utf8_string_object );
510 #endif
511 Py_BEGIN_ALLOW_THREADS
512
513 result = libfsapfs_container_open(
514 pyfsapfs_container->container,
515 filename_narrow,
516 LIBFSAPFS_OPEN_READ,
517 &error );
518
519 Py_END_ALLOW_THREADS
520
521 Py_DecRef(
522 utf8_string_object );
523 #endif
524 if( result != 1 )
525 {
526 pyfsapfs_error_raise(
527 error,
528 PyExc_IOError,
529 "%s: unable to open container.",
530 function );
531
532 libcerror_error_free(
533 &error );
534
535 return( NULL );
536 }
537 Py_IncRef(
538 Py_None );
539
540 return( Py_None );
541 }
542 PyErr_Clear();
543
544 #if PY_MAJOR_VERSION >= 3
545 result = PyObject_IsInstance(
546 string_object,
547 (PyObject *) &PyBytes_Type );
548 #else
549 result = PyObject_IsInstance(
550 string_object,
551 (PyObject *) &PyString_Type );
552 #endif
553 if( result == -1 )
554 {
555 pyfsapfs_error_fetch_and_raise(
556 PyExc_RuntimeError,
557 "%s: unable to determine if string object is of type string.",
558 function );
559
560 return( NULL );
561 }
562 else if( result != 0 )
563 {
564 PyErr_Clear();
565
566 #if PY_MAJOR_VERSION >= 3
567 filename_narrow = PyBytes_AsString(
568 string_object );
569 #else
570 filename_narrow = PyString_AsString(
571 string_object );
572 #endif
573 Py_BEGIN_ALLOW_THREADS
574
575 result = libfsapfs_container_open(
576 pyfsapfs_container->container,
577 filename_narrow,
578 LIBFSAPFS_OPEN_READ,
579 &error );
580
581 Py_END_ALLOW_THREADS
582
583 if( result != 1 )
584 {
585 pyfsapfs_error_raise(
586 error,
587 PyExc_IOError,
588 "%s: unable to open container.",
589 function );
590
591 libcerror_error_free(
592 &error );
593
594 return( NULL );
595 }
596 Py_IncRef(
597 Py_None );
598
599 return( Py_None );
600 }
601 PyErr_Format(
602 PyExc_TypeError,
603 "%s: unsupported string object type.",
604 function );
605
606 return( NULL );
607 }
608
609 /* Opens a container using a file-like object
610 * Returns a Python object if successful or NULL on error
611 */
pyfsapfs_container_open_file_object(pyfsapfs_container_t * pyfsapfs_container,PyObject * arguments,PyObject * keywords)612 PyObject *pyfsapfs_container_open_file_object(
613 pyfsapfs_container_t *pyfsapfs_container,
614 PyObject *arguments,
615 PyObject *keywords )
616 {
617 PyObject *file_object = NULL;
618 libcerror_error_t *error = NULL;
619 static char *function = "pyfsapfs_container_open_file_object";
620 static char *keyword_list[] = { "file_object", "mode", NULL };
621 char *mode = NULL;
622 int result = 0;
623
624 if( pyfsapfs_container == NULL )
625 {
626 PyErr_Format(
627 PyExc_ValueError,
628 "%s: invalid container.",
629 function );
630
631 return( NULL );
632 }
633 if( PyArg_ParseTupleAndKeywords(
634 arguments,
635 keywords,
636 "O|s",
637 keyword_list,
638 &file_object,
639 &mode ) == 0 )
640 {
641 return( NULL );
642 }
643 if( ( mode != NULL )
644 && ( mode[ 0 ] != 'r' ) )
645 {
646 PyErr_Format(
647 PyExc_ValueError,
648 "%s: unsupported mode: %s.",
649 function,
650 mode );
651
652 return( NULL );
653 }
654 PyErr_Clear();
655
656 result = PyObject_HasAttrString(
657 file_object,
658 "read" );
659
660 if( result != 1 )
661 {
662 PyErr_Format(
663 PyExc_TypeError,
664 "%s: unsupported file object - missing read attribute.",
665 function );
666
667 return( NULL );
668 }
669 PyErr_Clear();
670
671 result = PyObject_HasAttrString(
672 file_object,
673 "seek" );
674
675 if( result != 1 )
676 {
677 PyErr_Format(
678 PyExc_TypeError,
679 "%s: unsupported file object - missing seek attribute.",
680 function );
681
682 return( NULL );
683 }
684 if( pyfsapfs_container->file_io_handle != NULL )
685 {
686 pyfsapfs_error_raise(
687 error,
688 PyExc_IOError,
689 "%s: invalid container - file IO handle already set.",
690 function );
691
692 goto on_error;
693 }
694 if( pyfsapfs_file_object_initialize(
695 &( pyfsapfs_container->file_io_handle ),
696 file_object,
697 &error ) != 1 )
698 {
699 pyfsapfs_error_raise(
700 error,
701 PyExc_MemoryError,
702 "%s: unable to initialize file IO handle.",
703 function );
704
705 libcerror_error_free(
706 &error );
707
708 goto on_error;
709 }
710 Py_BEGIN_ALLOW_THREADS
711
712 result = libfsapfs_container_open_file_io_handle(
713 pyfsapfs_container->container,
714 pyfsapfs_container->file_io_handle,
715 LIBFSAPFS_OPEN_READ,
716 &error );
717
718 Py_END_ALLOW_THREADS
719
720 if( result != 1 )
721 {
722 pyfsapfs_error_raise(
723 error,
724 PyExc_IOError,
725 "%s: unable to open container.",
726 function );
727
728 libcerror_error_free(
729 &error );
730
731 goto on_error;
732 }
733 Py_IncRef(
734 Py_None );
735
736 return( Py_None );
737
738 on_error:
739 if( pyfsapfs_container->file_io_handle != NULL )
740 {
741 libbfio_handle_free(
742 &( pyfsapfs_container->file_io_handle ),
743 NULL );
744 }
745 return( NULL );
746 }
747
748 /* Closes a container
749 * Returns a Python object if successful or NULL on error
750 */
pyfsapfs_container_close(pyfsapfs_container_t * pyfsapfs_container,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)751 PyObject *pyfsapfs_container_close(
752 pyfsapfs_container_t *pyfsapfs_container,
753 PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
754 {
755 libcerror_error_t *error = NULL;
756 static char *function = "pyfsapfs_container_close";
757 int result = 0;
758
759 PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
760
761 if( pyfsapfs_container == NULL )
762 {
763 PyErr_Format(
764 PyExc_ValueError,
765 "%s: invalid container.",
766 function );
767
768 return( NULL );
769 }
770 Py_BEGIN_ALLOW_THREADS
771
772 result = libfsapfs_container_close(
773 pyfsapfs_container->container,
774 &error );
775
776 Py_END_ALLOW_THREADS
777
778 if( result != 0 )
779 {
780 pyfsapfs_error_raise(
781 error,
782 PyExc_IOError,
783 "%s: unable to close container.",
784 function );
785
786 libcerror_error_free(
787 &error );
788
789 return( NULL );
790 }
791 if( pyfsapfs_container->file_io_handle != NULL )
792 {
793 Py_BEGIN_ALLOW_THREADS
794
795 result = libbfio_handle_free(
796 &( pyfsapfs_container->file_io_handle ),
797 &error );
798
799 Py_END_ALLOW_THREADS
800
801 if( result != 1 )
802 {
803 pyfsapfs_error_raise(
804 error,
805 PyExc_MemoryError,
806 "%s: unable to free libbfio file IO handle.",
807 function );
808
809 libcerror_error_free(
810 &error );
811
812 return( NULL );
813 }
814 }
815 Py_IncRef(
816 Py_None );
817
818 return( Py_None );
819 }
820
821 /* Determines if the container is locked
822 * Returns a Python object if successful or NULL on error
823 */
pyfsapfs_container_is_locked(pyfsapfs_container_t * pyfsapfs_container,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)824 PyObject *pyfsapfs_container_is_locked(
825 pyfsapfs_container_t *pyfsapfs_container,
826 PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
827 {
828 libcerror_error_t *error = NULL;
829 static char *function = "pyfsapfs_container_is_locked";
830 int result = 0;
831
832 PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
833
834 if( pyfsapfs_container == NULL )
835 {
836 PyErr_Format(
837 PyExc_ValueError,
838 "%s: invalid container.",
839 function );
840
841 return( NULL );
842 }
843 Py_BEGIN_ALLOW_THREADS
844
845 result = libfsapfs_container_is_locked(
846 pyfsapfs_container->container,
847 &error );
848
849 Py_END_ALLOW_THREADS
850
851 if( result == -1 )
852 {
853 pyfsapfs_error_raise(
854 error,
855 PyExc_IOError,
856 "%s: unable to determine if container is locked.",
857 function );
858
859 libcerror_error_free(
860 &error );
861
862 return( NULL );
863 }
864 if( result != 0 )
865 {
866 Py_IncRef(
867 (PyObject *) Py_True );
868
869 return( Py_True );
870 }
871 Py_IncRef(
872 (PyObject *) Py_False );
873
874 return( Py_False );
875 }
876
877 /* Retrieves the size
878 * Returns a Python object if successful or NULL on error
879 */
pyfsapfs_container_get_size(pyfsapfs_container_t * pyfsapfs_container,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)880 PyObject *pyfsapfs_container_get_size(
881 pyfsapfs_container_t *pyfsapfs_container,
882 PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
883 {
884 PyObject *integer_object = NULL;
885 libcerror_error_t *error = NULL;
886 static char *function = "pyfsapfs_container_get_size";
887 size64_t size = 0;
888 int result = 0;
889
890 PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
891
892 if( pyfsapfs_container == NULL )
893 {
894 PyErr_Format(
895 PyExc_ValueError,
896 "%s: invalid container.",
897 function );
898
899 return( NULL );
900 }
901 Py_BEGIN_ALLOW_THREADS
902
903 result = libfsapfs_container_get_size(
904 pyfsapfs_container->container,
905 &size,
906 &error );
907
908 Py_END_ALLOW_THREADS
909
910 if( result != 1 )
911 {
912 pyfsapfs_error_raise(
913 error,
914 PyExc_IOError,
915 "%s: failed to retrieve size.",
916 function );
917
918 libcerror_error_free(
919 &error );
920
921 return( NULL );
922 }
923 integer_object = pyfsapfs_integer_unsigned_new_from_64bit(
924 (uint64_t) size );
925
926 return( integer_object );
927 }
928
929 /* Retrieves the identifier
930 * Returns a Python object if successful or NULL on error
931 */
pyfsapfs_container_get_identifier(pyfsapfs_container_t * pyfsapfs_container,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)932 PyObject *pyfsapfs_container_get_identifier(
933 pyfsapfs_container_t *pyfsapfs_container,
934 PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
935 {
936 uint8_t uuid_data[ 16 ];
937
938 PyObject *string_object = NULL;
939 libcerror_error_t *error = NULL;
940 static char *function = "pyfsapfs_container_get_identifier";
941 int result = 0;
942
943 PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
944
945 if( pyfsapfs_container == NULL )
946 {
947 PyErr_Format(
948 PyExc_ValueError,
949 "%s: invalid container.",
950 function );
951
952 return( NULL );
953 }
954 Py_BEGIN_ALLOW_THREADS
955
956 result = libfsapfs_container_get_identifier(
957 pyfsapfs_container->container,
958 uuid_data,
959 16,
960 &error );
961
962 Py_END_ALLOW_THREADS
963
964 if( result != 1 )
965 {
966 pyfsapfs_error_raise(
967 error,
968 PyExc_IOError,
969 "%s: unable to retrieve identifier.",
970 function );
971
972 libcerror_error_free(
973 &error );
974
975 return( NULL );
976 }
977 string_object = pyfsapfs_string_new_from_guid(
978 uuid_data,
979 16 );
980
981 if( string_object == NULL )
982 {
983 PyErr_Format(
984 PyExc_IOError,
985 "%s: unable to convert UUID into Unicode object.",
986 function );
987
988 return( NULL );
989 }
990 return( string_object );
991 }
992
993 /* Retrieves the number of volumes
994 * Returns a Python object if successful or NULL on error
995 */
pyfsapfs_container_get_number_of_volumes(pyfsapfs_container_t * pyfsapfs_container,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)996 PyObject *pyfsapfs_container_get_number_of_volumes(
997 pyfsapfs_container_t *pyfsapfs_container,
998 PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
999 {
1000 PyObject *integer_object = NULL;
1001 libcerror_error_t *error = NULL;
1002 static char *function = "pyfsapfs_container_get_number_of_volumes";
1003 int number_of_volumes = 0;
1004 int result = 0;
1005
1006 PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1007
1008 if( pyfsapfs_container == NULL )
1009 {
1010 PyErr_Format(
1011 PyExc_ValueError,
1012 "%s: invalid container.",
1013 function );
1014
1015 return( NULL );
1016 }
1017 Py_BEGIN_ALLOW_THREADS
1018
1019 result = libfsapfs_container_get_number_of_volumes(
1020 pyfsapfs_container->container,
1021 &number_of_volumes,
1022 &error );
1023
1024 Py_END_ALLOW_THREADS
1025
1026 if( result != 1 )
1027 {
1028 pyfsapfs_error_raise(
1029 error,
1030 PyExc_IOError,
1031 "%s: unable to retrieve number of volumes.",
1032 function );
1033
1034 libcerror_error_free(
1035 &error );
1036
1037 return( NULL );
1038 }
1039 #if PY_MAJOR_VERSION >= 3
1040 integer_object = PyLong_FromLong(
1041 (long) number_of_volumes );
1042 #else
1043 integer_object = PyInt_FromLong(
1044 (long) number_of_volumes );
1045 #endif
1046 return( integer_object );
1047 }
1048
1049 /* Retrieves a specific of volume by index
1050 * Returns a Python object if successful or NULL on error
1051 */
pyfsapfs_container_get_volume_by_index(PyObject * pyfsapfs_container,int volume_index)1052 PyObject *pyfsapfs_container_get_volume_by_index(
1053 PyObject *pyfsapfs_container,
1054 int volume_index )
1055 {
1056 PyObject *volume_object = NULL;
1057 libcerror_error_t *error = NULL;
1058 libfsapfs_volume_t *volume = NULL;
1059 static char *function = "pyfsapfs_container_get_volume_by_index";
1060 int result = 0;
1061
1062 if( pyfsapfs_container == NULL )
1063 {
1064 PyErr_Format(
1065 PyExc_ValueError,
1066 "%s: invalid container.",
1067 function );
1068
1069 return( NULL );
1070 }
1071 Py_BEGIN_ALLOW_THREADS
1072
1073 result = libfsapfs_container_get_volume_by_index(
1074 ( (pyfsapfs_container_t *) pyfsapfs_container )->container,
1075 volume_index,
1076 &volume,
1077 &error );
1078
1079 Py_END_ALLOW_THREADS
1080
1081 if( result != 1 )
1082 {
1083 pyfsapfs_error_raise(
1084 error,
1085 PyExc_IOError,
1086 "%s: unable to retrieve of volume: %d.",
1087 function,
1088 volume_index );
1089
1090 libcerror_error_free(
1091 &error );
1092
1093 goto on_error;
1094 }
1095 volume_object = pyfsapfs_volume_new(
1096 volume,
1097 pyfsapfs_container );
1098
1099 if( volume_object == NULL )
1100 {
1101 PyErr_Format(
1102 PyExc_MemoryError,
1103 "%s: unable to create volume object.",
1104 function );
1105
1106 goto on_error;
1107 }
1108 return( volume_object );
1109
1110 on_error:
1111 if( volume != NULL )
1112 {
1113 libfsapfs_volume_free(
1114 &volume,
1115 NULL );
1116 }
1117 return( NULL );
1118 }
1119
1120 /* Retrieves a specific of volume
1121 * Returns a Python object if successful or NULL on error
1122 */
pyfsapfs_container_get_volume(pyfsapfs_container_t * pyfsapfs_container,PyObject * arguments,PyObject * keywords)1123 PyObject *pyfsapfs_container_get_volume(
1124 pyfsapfs_container_t *pyfsapfs_container,
1125 PyObject *arguments,
1126 PyObject *keywords )
1127 {
1128 PyObject *volume_object = NULL;
1129 static char *keyword_list[] = { "volume_index", NULL };
1130 int volume_index = 0;
1131
1132 if( PyArg_ParseTupleAndKeywords(
1133 arguments,
1134 keywords,
1135 "i",
1136 keyword_list,
1137 &volume_index ) == 0 )
1138 {
1139 return( NULL );
1140 }
1141 volume_object = pyfsapfs_container_get_volume_by_index(
1142 (PyObject *) pyfsapfs_container,
1143 volume_index );
1144
1145 return( volume_object );
1146 }
1147
1148 /* Retrieves a sequence and iterator object for the volumes
1149 * Returns a Python object if successful or NULL on error
1150 */
pyfsapfs_container_get_volumes(pyfsapfs_container_t * pyfsapfs_container,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1151 PyObject *pyfsapfs_container_get_volumes(
1152 pyfsapfs_container_t *pyfsapfs_container,
1153 PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1154 {
1155 PyObject *sequence_object = NULL;
1156 libcerror_error_t *error = NULL;
1157 static char *function = "pyfsapfs_container_get_volumes";
1158 int number_of_volumes = 0;
1159 int result = 0;
1160
1161 PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1162
1163 if( pyfsapfs_container == NULL )
1164 {
1165 PyErr_Format(
1166 PyExc_ValueError,
1167 "%s: invalid container.",
1168 function );
1169
1170 return( NULL );
1171 }
1172 Py_BEGIN_ALLOW_THREADS
1173
1174 result = libfsapfs_container_get_number_of_volumes(
1175 pyfsapfs_container->container,
1176 &number_of_volumes,
1177 &error );
1178
1179 Py_END_ALLOW_THREADS
1180
1181 if( result != 1 )
1182 {
1183 pyfsapfs_error_raise(
1184 error,
1185 PyExc_IOError,
1186 "%s: unable to retrieve number of volumes.",
1187 function );
1188
1189 libcerror_error_free(
1190 &error );
1191
1192 return( NULL );
1193 }
1194 sequence_object = pyfsapfs_volumes_new(
1195 (PyObject *) pyfsapfs_container,
1196 &pyfsapfs_container_get_volume_by_index,
1197 number_of_volumes );
1198
1199 if( sequence_object == NULL )
1200 {
1201 pyfsapfs_error_raise(
1202 error,
1203 PyExc_MemoryError,
1204 "%s: unable to create sequence object.",
1205 function );
1206
1207 return( NULL );
1208 }
1209 return( sequence_object );
1210 }
1211
1212