1 /*
2 * Python object wrapper of libvslvm_physical_volume_t
3 *
4 * Copyright (C) 2014-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 "pyvslvm_error.h"
30 #include "pyvslvm_integer.h"
31 #include "pyvslvm_libcerror.h"
32 #include "pyvslvm_libvslvm.h"
33 #include "pyvslvm_physical_volume.h"
34 #include "pyvslvm_python.h"
35 #include "pyvslvm_unused.h"
36 #include "pyvslvm_volume_group.h"
37
38 PyMethodDef pyvslvm_physical_volume_object_methods[] = {
39
40 /* Functions to access the physical volume values */
41
42 { "get_name",
43 (PyCFunction) pyvslvm_physical_volume_get_name,
44 METH_NOARGS,
45 "get_name() -> Unicode string or None\n"
46 "\n"
47 "Retrieves the name." },
48
49 { "get_identifier",
50 (PyCFunction) pyvslvm_physical_volume_get_identifier,
51 METH_NOARGS,
52 "get_identifier() -> Unicode string or None\n"
53 "\n"
54 "Retrieves the identifier." },
55
56 { "get_device_path",
57 (PyCFunction) pyvslvm_physical_volume_get_device_path,
58 METH_NOARGS,
59 "get_device_path() -> Unicode string or None\n"
60 "\n"
61 "Retrieves the device path." },
62
63 { "get_size",
64 (PyCFunction) pyvslvm_physical_volume_get_size,
65 METH_NOARGS,
66 "get_size() -> Integer\n"
67 "\n"
68 "Retrieves the size of the volume." },
69
70 /* Sentinel */
71 { NULL, NULL, 0, NULL }
72 };
73
74 PyGetSetDef pyvslvm_physical_volume_object_get_set_definitions[] = {
75
76 { "name",
77 (getter) pyvslvm_physical_volume_get_name,
78 (setter) 0,
79 "The name.",
80 NULL },
81
82 { "identifier",
83 (getter) pyvslvm_physical_volume_get_identifier,
84 (setter) 0,
85 "The identifier.",
86 NULL },
87
88 { "device_path",
89 (getter) pyvslvm_physical_volume_get_device_path,
90 (setter) 0,
91 "The device path.",
92 NULL },
93
94 { "size",
95 (getter) pyvslvm_physical_volume_get_size,
96 (setter) 0,
97 "The volume size.",
98 NULL },
99
100 /* Sentinel */
101 { NULL, NULL, NULL, NULL, NULL }
102 };
103
104 PyTypeObject pyvslvm_physical_volume_type_object = {
105 PyVarObject_HEAD_INIT( NULL, 0 )
106
107 /* tp_name */
108 "pyvslvm.physical_volume",
109 /* tp_basicsize */
110 sizeof( pyvslvm_physical_volume_t ),
111 /* tp_itemsize */
112 0,
113 /* tp_dealloc */
114 (destructor) pyvslvm_physical_volume_free,
115 /* tp_print */
116 0,
117 /* tp_getattr */
118 0,
119 /* tp_setattr */
120 0,
121 /* tp_compare */
122 0,
123 /* tp_repr */
124 0,
125 /* tp_as_number */
126 0,
127 /* tp_as_sequence */
128 0,
129 /* tp_as_mapping */
130 0,
131 /* tp_hash */
132 0,
133 /* tp_call */
134 0,
135 /* tp_str */
136 0,
137 /* tp_getattro */
138 0,
139 /* tp_setattro */
140 0,
141 /* tp_as_buffer */
142 0,
143 /* tp_flags */
144 Py_TPFLAGS_DEFAULT,
145 /* tp_doc */
146 "pyvslvm physical volume object (wraps libvslvm_physical_volume_t)",
147 /* tp_traverse */
148 0,
149 /* tp_clear */
150 0,
151 /* tp_richcompare */
152 0,
153 /* tp_weaklistoffset */
154 0,
155 /* tp_iter */
156 0,
157 /* tp_iternext */
158 0,
159 /* tp_methods */
160 pyvslvm_physical_volume_object_methods,
161 /* tp_members */
162 0,
163 /* tp_getset */
164 pyvslvm_physical_volume_object_get_set_definitions,
165 /* tp_base */
166 0,
167 /* tp_dict */
168 0,
169 /* tp_descr_get */
170 0,
171 /* tp_descr_set */
172 0,
173 /* tp_dictoffset */
174 0,
175 /* tp_init */
176 (initproc) pyvslvm_physical_volume_init,
177 /* tp_alloc */
178 0,
179 /* tp_new */
180 0,
181 /* tp_free */
182 0,
183 /* tp_is_gc */
184 0,
185 /* tp_bases */
186 NULL,
187 /* tp_mro */
188 NULL,
189 /* tp_cache */
190 NULL,
191 /* tp_subclasses */
192 NULL,
193 /* tp_weaklist */
194 NULL,
195 /* tp_del */
196 0
197 };
198
199 /* Creates a new physical volume object
200 * Returns a Python object if successful or NULL on error
201 */
pyvslvm_physical_volume_new(libvslvm_physical_volume_t * physical_volume,pyvslvm_volume_group_t * volume_group_object)202 PyObject *pyvslvm_physical_volume_new(
203 libvslvm_physical_volume_t *physical_volume,
204 pyvslvm_volume_group_t *volume_group_object )
205 {
206 pyvslvm_physical_volume_t *pyvslvm_physical_volume = NULL;
207 static char *function = "pyvslvm_physical_volume_new";
208
209 if( physical_volume == NULL )
210 {
211 PyErr_Format(
212 PyExc_TypeError,
213 "%s: invalid physical volume.",
214 function );
215
216 return( NULL );
217 }
218 pyvslvm_physical_volume = PyObject_New(
219 struct pyvslvm_physical_volume,
220 &pyvslvm_physical_volume_type_object );
221
222 if( pyvslvm_physical_volume == NULL )
223 {
224 PyErr_Format(
225 PyExc_MemoryError,
226 "%s: unable to initialize physical volume.",
227 function );
228
229 goto on_error;
230 }
231 if( pyvslvm_physical_volume_init(
232 pyvslvm_physical_volume ) != 0 )
233 {
234 PyErr_Format(
235 PyExc_MemoryError,
236 "%s: unable to initialize physical volume.",
237 function );
238
239 goto on_error;
240 }
241 pyvslvm_physical_volume->physical_volume = physical_volume;
242 pyvslvm_physical_volume->volume_group_object = volume_group_object;
243
244 Py_IncRef(
245 (PyObject *) pyvslvm_physical_volume->volume_group_object );
246
247 return( (PyObject *) pyvslvm_physical_volume );
248
249 on_error:
250 if( pyvslvm_physical_volume != NULL )
251 {
252 Py_DecRef(
253 (PyObject *) pyvslvm_physical_volume );
254 }
255 return( NULL );
256 }
257
258 /* Initializes a physical volume object
259 * Returns 0 if successful or -1 on error
260 */
pyvslvm_physical_volume_init(pyvslvm_physical_volume_t * pyvslvm_physical_volume)261 int pyvslvm_physical_volume_init(
262 pyvslvm_physical_volume_t *pyvslvm_physical_volume )
263 {
264 static char *function = "pyvslvm_physical_volume_init";
265
266 if( pyvslvm_physical_volume == NULL )
267 {
268 PyErr_Format(
269 PyExc_TypeError,
270 "%s: invalid physical volume.",
271 function );
272
273 return( -1 );
274 }
275 /* Make sure libvslvm physical volume is set to NULL
276 */
277 pyvslvm_physical_volume->physical_volume = NULL;
278
279 return( 0 );
280 }
281
282 /* Frees a physical volume object
283 */
pyvslvm_physical_volume_free(pyvslvm_physical_volume_t * pyvslvm_physical_volume)284 void pyvslvm_physical_volume_free(
285 pyvslvm_physical_volume_t *pyvslvm_physical_volume )
286 {
287 libcerror_error_t *error = NULL;
288 struct _typeobject *ob_type = NULL;
289 static char *function = "pyvslvm_physical_volume_free";
290
291 if( pyvslvm_physical_volume == NULL )
292 {
293 PyErr_Format(
294 PyExc_TypeError,
295 "%s: invalid physical volume.",
296 function );
297
298 return;
299 }
300 if( pyvslvm_physical_volume->physical_volume == NULL )
301 {
302 PyErr_Format(
303 PyExc_TypeError,
304 "%s: invalid physical volume - missing libvslvm physical volume.",
305 function );
306
307 return;
308 }
309 ob_type = Py_TYPE(
310 pyvslvm_physical_volume );
311
312 if( ob_type == NULL )
313 {
314 PyErr_Format(
315 PyExc_ValueError,
316 "%s: missing ob_type.",
317 function );
318
319 return;
320 }
321 if( ob_type->tp_free == NULL )
322 {
323 PyErr_Format(
324 PyExc_ValueError,
325 "%s: invalid ob_type - missing tp_free.",
326 function );
327
328 return;
329 }
330 if( libvslvm_physical_volume_free(
331 &( pyvslvm_physical_volume->physical_volume ),
332 &error ) != 1 )
333 {
334 pyvslvm_error_raise(
335 error,
336 PyExc_IOError,
337 "%s: unable to free libvslvm physical volume.",
338 function );
339
340 libcerror_error_free(
341 &error );
342 }
343 if( pyvslvm_physical_volume->volume_group_object != NULL )
344 {
345 Py_DecRef(
346 (PyObject *) pyvslvm_physical_volume->volume_group_object );
347 }
348 ob_type->tp_free(
349 (PyObject*) pyvslvm_physical_volume );
350 }
351
352 /* Retrieves the name
353 * Returns a Python object if successful or NULL on error
354 */
pyvslvm_physical_volume_get_name(pyvslvm_physical_volume_t * pyvslvm_physical_volume,PyObject * arguments PYVSLVM_ATTRIBUTE_UNUSED)355 PyObject *pyvslvm_physical_volume_get_name(
356 pyvslvm_physical_volume_t *pyvslvm_physical_volume,
357 PyObject *arguments PYVSLVM_ATTRIBUTE_UNUSED )
358 {
359 libcerror_error_t *error = NULL;
360 PyObject *string_object = NULL;
361 char *name = NULL;
362 const char *errors = NULL;
363 static char *function = "pyvslvm_physical_volume_get_name";
364 size_t name_size = 0;
365 int result = 0;
366
367 PYVSLVM_UNREFERENCED_PARAMETER( arguments )
368
369 if( pyvslvm_physical_volume == NULL )
370 {
371 PyErr_Format(
372 PyExc_TypeError,
373 "%s: invalid physical volume.",
374 function );
375
376 return( NULL );
377 }
378 Py_BEGIN_ALLOW_THREADS
379
380 result = libvslvm_physical_volume_get_name_size(
381 pyvslvm_physical_volume->physical_volume,
382 &name_size,
383 &error );
384
385 Py_END_ALLOW_THREADS
386
387 if( result == -1 )
388 {
389 pyvslvm_error_raise(
390 error,
391 PyExc_IOError,
392 "%s: unable to retrieve name size.",
393 function );
394
395 libcerror_error_free(
396 &error );
397
398 goto on_error;
399 }
400 else if( ( result == 0 )
401 || ( name_size == 0 ) )
402 {
403 Py_IncRef(
404 Py_None );
405
406 return( Py_None );
407 }
408 name = (char *) PyMem_Malloc(
409 sizeof( char ) * name_size );
410
411 if( name == NULL )
412 {
413 PyErr_Format(
414 PyExc_IOError,
415 "%s: unable to create name.",
416 function );
417
418 goto on_error;
419 }
420 Py_BEGIN_ALLOW_THREADS
421
422 result = libvslvm_physical_volume_get_name(
423 pyvslvm_physical_volume->physical_volume,
424 name,
425 name_size,
426 &error );
427
428 Py_END_ALLOW_THREADS
429
430 if( result != 1 )
431 {
432 pyvslvm_error_raise(
433 error,
434 PyExc_IOError,
435 "%s: unable to retrieve name.",
436 function );
437
438 libcerror_error_free(
439 &error );
440
441 goto on_error;
442 }
443 /* Pass the string length to PyUnicode_DecodeUTF8
444 * otherwise it makes the end of string character is part
445 * of the string
446 */
447 string_object = PyUnicode_DecodeUTF8(
448 name,
449 (Py_ssize_t) name_size - 1,
450 errors );
451
452 PyMem_Free(
453 name );
454
455 return( string_object );
456
457 on_error:
458 if( name != NULL )
459 {
460 PyMem_Free(
461 name );
462 }
463 return( NULL );
464 }
465
466 /* Retrieves the identifier
467 * Returns a Python object if successful or NULL on error
468 */
pyvslvm_physical_volume_get_identifier(pyvslvm_physical_volume_t * pyvslvm_physical_volume,PyObject * arguments PYVSLVM_ATTRIBUTE_UNUSED)469 PyObject *pyvslvm_physical_volume_get_identifier(
470 pyvslvm_physical_volume_t *pyvslvm_physical_volume,
471 PyObject *arguments PYVSLVM_ATTRIBUTE_UNUSED )
472 {
473 libcerror_error_t *error = NULL;
474 PyObject *string_object = NULL;
475 char *identifier = NULL;
476 const char *errors = NULL;
477 static char *function = "pyvslvm_physical_volume_get_identifier";
478 size_t identifier_size = 0;
479 int result = 0;
480
481 PYVSLVM_UNREFERENCED_PARAMETER( arguments )
482
483 if( pyvslvm_physical_volume == NULL )
484 {
485 PyErr_Format(
486 PyExc_TypeError,
487 "%s: invalid physical volume.",
488 function );
489
490 return( NULL );
491 }
492 Py_BEGIN_ALLOW_THREADS
493
494 result = libvslvm_physical_volume_get_identifier_size(
495 pyvslvm_physical_volume->physical_volume,
496 &identifier_size,
497 &error );
498
499 Py_END_ALLOW_THREADS
500
501 if( result == -1 )
502 {
503 pyvslvm_error_raise(
504 error,
505 PyExc_IOError,
506 "%s: unable to retrieve identifier size.",
507 function );
508
509 libcerror_error_free(
510 &error );
511
512 goto on_error;
513 }
514 else if( ( result == 0 )
515 || ( identifier_size == 0 ) )
516 {
517 Py_IncRef(
518 Py_None );
519
520 return( Py_None );
521 }
522 identifier = (char *) PyMem_Malloc(
523 sizeof( char ) * identifier_size );
524
525 if( identifier == NULL )
526 {
527 PyErr_Format(
528 PyExc_IOError,
529 "%s: unable to create identifier.",
530 function );
531
532 goto on_error;
533 }
534 Py_BEGIN_ALLOW_THREADS
535
536 result = libvslvm_physical_volume_get_identifier(
537 pyvslvm_physical_volume->physical_volume,
538 identifier,
539 identifier_size,
540 &error );
541
542 Py_END_ALLOW_THREADS
543
544 if( result != 1 )
545 {
546 pyvslvm_error_raise(
547 error,
548 PyExc_IOError,
549 "%s: unable to retrieve identifier.",
550 function );
551
552 libcerror_error_free(
553 &error );
554
555 goto on_error;
556 }
557 /* Pass the string length to PyUnicode_DecodeUTF8
558 * otherwise it makes the end of string character is part
559 * of the string
560 */
561 string_object = PyUnicode_DecodeUTF8(
562 identifier,
563 (Py_ssize_t) identifier_size - 1,
564 errors );
565
566 PyMem_Free(
567 identifier );
568
569 return( string_object );
570
571 on_error:
572 if( identifier != NULL )
573 {
574 PyMem_Free(
575 identifier );
576 }
577 return( NULL );
578 }
579
580 /* Retrieves the device path
581 * Returns a Python object if successful or NULL on error
582 */
pyvslvm_physical_volume_get_device_path(pyvslvm_physical_volume_t * pyvslvm_physical_volume,PyObject * arguments PYVSLVM_ATTRIBUTE_UNUSED)583 PyObject *pyvslvm_physical_volume_get_device_path(
584 pyvslvm_physical_volume_t *pyvslvm_physical_volume,
585 PyObject *arguments PYVSLVM_ATTRIBUTE_UNUSED )
586 {
587 libcerror_error_t *error = NULL;
588 PyObject *string_object = NULL;
589 char *device_path = NULL;
590 const char *errors = NULL;
591 static char *function = "pyvslvm_physical_volume_get_device_path";
592 size_t device_path_size = 0;
593 int result = 0;
594
595 PYVSLVM_UNREFERENCED_PARAMETER( arguments )
596
597 if( pyvslvm_physical_volume == NULL )
598 {
599 PyErr_Format(
600 PyExc_TypeError,
601 "%s: invalid physical volume.",
602 function );
603
604 return( NULL );
605 }
606 Py_BEGIN_ALLOW_THREADS
607
608 result = libvslvm_physical_volume_get_device_path_size(
609 pyvslvm_physical_volume->physical_volume,
610 &device_path_size,
611 &error );
612
613 Py_END_ALLOW_THREADS
614
615 if( result == -1 )
616 {
617 pyvslvm_error_raise(
618 error,
619 PyExc_IOError,
620 "%s: unable to retrieve device path size.",
621 function );
622
623 libcerror_error_free(
624 &error );
625
626 goto on_error;
627 }
628 else if( ( result == 0 )
629 || ( device_path_size == 0 ) )
630 {
631 Py_IncRef(
632 Py_None );
633
634 return( Py_None );
635 }
636 device_path = (char *) PyMem_Malloc(
637 sizeof( char ) * device_path_size );
638
639 if( device_path == NULL )
640 {
641 PyErr_Format(
642 PyExc_IOError,
643 "%s: unable to create device path.",
644 function );
645
646 goto on_error;
647 }
648 Py_BEGIN_ALLOW_THREADS
649
650 result = libvslvm_physical_volume_get_device_path(
651 pyvslvm_physical_volume->physical_volume,
652 device_path,
653 device_path_size,
654 &error );
655
656 Py_END_ALLOW_THREADS
657
658 if( result != 1 )
659 {
660 pyvslvm_error_raise(
661 error,
662 PyExc_IOError,
663 "%s: unable to retrieve device path.",
664 function );
665
666 libcerror_error_free(
667 &error );
668
669 goto on_error;
670 }
671 /* Pass the string length to PyUnicode_DecodeUTF8
672 * otherwise it makes the end of string character is part
673 * of the string
674 */
675 string_object = PyUnicode_DecodeUTF8(
676 device_path,
677 (Py_ssize_t) device_path_size - 1,
678 errors );
679
680 PyMem_Free(
681 device_path );
682
683 return( string_object );
684
685 on_error:
686 if( device_path != NULL )
687 {
688 PyMem_Free(
689 device_path );
690 }
691 return( NULL );
692 }
693
694 /* Retrieves the size
695 * Returns a Python object if successful or NULL on error
696 */
pyvslvm_physical_volume_get_size(pyvslvm_physical_volume_t * pyvslvm_physical_volume,PyObject * arguments PYVSLVM_ATTRIBUTE_UNUSED)697 PyObject *pyvslvm_physical_volume_get_size(
698 pyvslvm_physical_volume_t *pyvslvm_physical_volume,
699 PyObject *arguments PYVSLVM_ATTRIBUTE_UNUSED )
700 {
701 libcerror_error_t *error = NULL;
702 PyObject *integer_object = NULL;
703 static char *function = "pyvslvm_physical_volume_get_size";
704 size64_t size = 0;
705 int result = 0;
706
707 PYVSLVM_UNREFERENCED_PARAMETER( arguments )
708
709 if( pyvslvm_physical_volume == NULL )
710 {
711 PyErr_Format(
712 PyExc_TypeError,
713 "%s: invalid physical volume.",
714 function );
715
716 return( NULL );
717 }
718 Py_BEGIN_ALLOW_THREADS
719
720 result = libvslvm_physical_volume_get_size(
721 pyvslvm_physical_volume->physical_volume,
722 &size,
723 &error );
724
725 Py_END_ALLOW_THREADS
726
727 if( result != 1 )
728 {
729 pyvslvm_error_raise(
730 error,
731 PyExc_IOError,
732 "%s: failed to retrieve size.",
733 function );
734
735 libcerror_error_free(
736 &error );
737
738 return( NULL );
739 }
740 integer_object = pyvslvm_integer_unsigned_new_from_64bit(
741 (uint64_t) size );
742
743 return( integer_object );
744 }
745
746