1 /*
2  * Python object wrapper of libvslvm_logical_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_logical_volume.h"
34 #include "pyvslvm_python.h"
35 #include "pyvslvm_segment.h"
36 #include "pyvslvm_segments.h"
37 #include "pyvslvm_unused.h"
38 #include "pyvslvm_volume_group.h"
39 
40 PyMethodDef pyvslvm_logical_volume_object_methods[] = {
41 
42 	/* Functions to access the logical volume data */
43 
44 	{ "read_buffer",
45 	  (PyCFunction) pyvslvm_logical_volume_read_buffer,
46 	  METH_VARARGS | METH_KEYWORDS,
47 	  "read_buffer(size) -> String\n"
48 	  "\n"
49 	  "Reads a buffer of data." },
50 
51 	{ "read_buffer_at_offset",
52 	  (PyCFunction) pyvslvm_logical_volume_read_buffer_at_offset,
53 	  METH_VARARGS | METH_KEYWORDS,
54 	  "read_buffer_at_offset(size, offset) -> String\n"
55 	  "\n"
56 	  "Reads a buffer of data at a specific offset." },
57 
58 	{ "seek_offset",
59 	  (PyCFunction) pyvslvm_logical_volume_seek_offset,
60 	  METH_VARARGS | METH_KEYWORDS,
61 	  "seek_offset(offset, whence) -> None\n"
62 	  "\n"
63 	  "Seeks an offset within the data." },
64 
65 	{ "get_offset",
66 	  (PyCFunction) pyvslvm_logical_volume_get_offset,
67 	  METH_NOARGS,
68 	  "get_offset() -> Integer\n"
69 	  "\n"
70 	  "Retrieves the current offset within the data." },
71 
72 	/* Some Pythonesque aliases */
73 
74 	{ "read",
75 	  (PyCFunction) pyvslvm_logical_volume_read_buffer,
76 	  METH_VARARGS | METH_KEYWORDS,
77 	  "read(size) -> String\n"
78 	  "\n"
79 	  "Reads a buffer of data." },
80 
81 	{ "seek",
82 	  (PyCFunction) pyvslvm_logical_volume_seek_offset,
83 	  METH_VARARGS | METH_KEYWORDS,
84 	  "seek(offset, whence) -> None\n"
85 	  "\n"
86 	  "Seeks an offset within the data." },
87 
88 	{ "tell",
89 	  (PyCFunction) pyvslvm_logical_volume_get_offset,
90 	  METH_NOARGS,
91 	  "tell() -> Integer\n"
92 	  "\n"
93 	  "Retrieves the current offset within the data." },
94 
95 	/* Functions to access the logical volume values */
96 
97 	{ "get_size",
98 	  (PyCFunction) pyvslvm_logical_volume_get_size,
99 	  METH_NOARGS,
100 	  "get_size() -> Integer\n"
101 	  "\n"
102 	  "Retrieves the size of the volume." },
103 
104 	{ "get_name",
105 	  (PyCFunction) pyvslvm_logical_volume_get_name,
106 	  METH_NOARGS,
107 	  "get_name() -> Unicode string or None\n"
108 	  "\n"
109 	  "Retrieves the name." },
110 
111 	{ "get_identifier",
112 	  (PyCFunction) pyvslvm_logical_volume_get_identifier,
113 	  METH_NOARGS,
114 	  "get_identifier() -> Unicode string or None\n"
115 	  "\n"
116 	  "Retrieves the identifier." },
117 
118 	/* Functions to access the segments */
119 
120 	{ "get_number_of_segments",
121 	  (PyCFunction) pyvslvm_logical_volume_get_number_of_segments,
122 	  METH_NOARGS,
123 	  "get_number_of_segments() -> Integer\n"
124 	  "\n"
125 	  "Retrieves the number of segments." },
126 
127 	{ "get_segment",
128 	  (PyCFunction) pyvslvm_logical_volume_get_segment,
129 	  METH_VARARGS | METH_KEYWORDS,
130 	  "get_segment(segment_index) -> Object or None\n"
131 	  "\n"
132 	  "Retrieves a specific segment." },
133 
134 	{ "get_segments",
135 	  (PyCFunction) pyvslvm_logical_volume_get_segments,
136 	  METH_VARARGS | METH_KEYWORDS,
137 	  "get_segments() -> Object\n"
138 	  "\n"
139 	  "Retrieves a sequence object of the segments." },
140 
141 	/* Sentinel */
142 	{ NULL, NULL, 0, NULL }
143 };
144 
145 PyGetSetDef pyvslvm_logical_volume_object_get_set_definitions[] = {
146 
147 	{ "size",
148 	  (getter) pyvslvm_logical_volume_get_size,
149 	  (setter) 0,
150 	  "The volume size.",
151 	  NULL },
152 
153 	{ "name",
154 	  (getter) pyvslvm_logical_volume_get_name,
155 	  (setter) 0,
156 	  "The name.",
157 	  NULL },
158 
159 	{ "identifier",
160 	  (getter) pyvslvm_logical_volume_get_identifier,
161 	  (setter) 0,
162 	  "The identifier.",
163 	  NULL },
164 
165 	{ "number_of_segments",
166 	  (getter) pyvslvm_logical_volume_get_number_of_segments,
167 	  (setter) 0,
168 	  "The number of segments.",
169 	  NULL },
170 
171 	{ "segments",
172 	  (getter) pyvslvm_logical_volume_get_segments,
173 	  (setter) 0,
174 	  "The segments.",
175 	  NULL },
176 
177 	/* Sentinel */
178 	{ NULL, NULL, NULL, NULL, NULL }
179 };
180 
181 PyTypeObject pyvslvm_logical_volume_type_object = {
182 	PyVarObject_HEAD_INIT( NULL, 0 )
183 
184 	/* tp_name */
185 	"pyvslvm.logical_volume",
186 	/* tp_basicsize */
187 	sizeof( pyvslvm_logical_volume_t ),
188 	/* tp_itemsize */
189 	0,
190 	/* tp_dealloc */
191 	(destructor) pyvslvm_logical_volume_free,
192 	/* tp_print */
193 	0,
194 	/* tp_getattr */
195 	0,
196 	/* tp_setattr */
197 	0,
198 	/* tp_compare */
199 	0,
200 	/* tp_repr */
201 	0,
202 	/* tp_as_number */
203 	0,
204 	/* tp_as_sequence */
205 	0,
206 	/* tp_as_mapping */
207 	0,
208 	/* tp_hash */
209 	0,
210 	/* tp_call */
211 	0,
212 	/* tp_str */
213 	0,
214 	/* tp_getattro */
215 	0,
216 	/* tp_setattro */
217 	0,
218 	/* tp_as_buffer */
219 	0,
220 	/* tp_flags */
221 	Py_TPFLAGS_DEFAULT,
222 	/* tp_doc */
223 	"pyvslvm logical volume object (wraps libvslvm_logical_volume_t)",
224 	/* tp_traverse */
225 	0,
226 	/* tp_clear */
227 	0,
228 	/* tp_richcompare */
229 	0,
230 	/* tp_weaklistoffset */
231 	0,
232 	/* tp_iter */
233 	0,
234 	/* tp_iternext */
235 	0,
236 	/* tp_methods */
237 	pyvslvm_logical_volume_object_methods,
238 	/* tp_members */
239 	0,
240 	/* tp_getset */
241 	pyvslvm_logical_volume_object_get_set_definitions,
242 	/* tp_base */
243 	0,
244 	/* tp_dict */
245 	0,
246 	/* tp_descr_get */
247 	0,
248 	/* tp_descr_set */
249 	0,
250 	/* tp_dictoffset */
251 	0,
252 	/* tp_init */
253 	(initproc) pyvslvm_logical_volume_init,
254 	/* tp_alloc */
255 	0,
256 	/* tp_new */
257 	0,
258 	/* tp_free */
259 	0,
260 	/* tp_is_gc */
261 	0,
262 	/* tp_bases */
263 	NULL,
264 	/* tp_mro */
265 	NULL,
266 	/* tp_cache */
267 	NULL,
268 	/* tp_subclasses */
269 	NULL,
270 	/* tp_weaklist */
271 	NULL,
272 	/* tp_del */
273 	0
274 };
275 
276 /* Creates a new logical volume object
277  * Returns a Python object if successful or NULL on error
278  */
pyvslvm_logical_volume_new(libvslvm_logical_volume_t * logical_volume,pyvslvm_volume_group_t * volume_group_object)279 PyObject *pyvslvm_logical_volume_new(
280            libvslvm_logical_volume_t *logical_volume,
281            pyvslvm_volume_group_t *volume_group_object )
282 {
283 	pyvslvm_logical_volume_t *pyvslvm_logical_volume = NULL;
284 	static char *function                            = "pyvslvm_logical_volume_new";
285 
286 	if( logical_volume == NULL )
287 	{
288 		PyErr_Format(
289 		 PyExc_TypeError,
290 		 "%s: invalid logical volume.",
291 		 function );
292 
293 		return( NULL );
294 	}
295 	pyvslvm_logical_volume = PyObject_New(
296 	                          struct pyvslvm_logical_volume,
297 	                          &pyvslvm_logical_volume_type_object );
298 
299 	if( pyvslvm_logical_volume == NULL )
300 	{
301 		PyErr_Format(
302 		 PyExc_MemoryError,
303 		 "%s: unable to initialize logical volume.",
304 		 function );
305 
306 		goto on_error;
307 	}
308 	if( pyvslvm_logical_volume_init(
309 	     pyvslvm_logical_volume ) != 0 )
310 	{
311 		PyErr_Format(
312 		 PyExc_MemoryError,
313 		 "%s: unable to initialize logical volume.",
314 		 function );
315 
316 		goto on_error;
317 	}
318 	pyvslvm_logical_volume->logical_volume      = logical_volume;
319 	pyvslvm_logical_volume->volume_group_object = volume_group_object;
320 
321 	Py_IncRef(
322 	 (PyObject *) pyvslvm_logical_volume->volume_group_object );
323 
324 	return( (PyObject *) pyvslvm_logical_volume );
325 
326 on_error:
327 	if( pyvslvm_logical_volume != NULL )
328 	{
329 		Py_DecRef(
330 		 (PyObject *) pyvslvm_logical_volume );
331 	}
332 	return( NULL );
333 }
334 
335 /* Initializes a logical volume object
336  * Returns 0 if successful or -1 on error
337  */
pyvslvm_logical_volume_init(pyvslvm_logical_volume_t * pyvslvm_logical_volume)338 int pyvslvm_logical_volume_init(
339      pyvslvm_logical_volume_t *pyvslvm_logical_volume )
340 {
341 	static char *function = "pyvslvm_logical_volume_init";
342 
343 	if( pyvslvm_logical_volume == NULL )
344 	{
345 		PyErr_Format(
346 		 PyExc_TypeError,
347 		 "%s: invalid logical volume.",
348 		 function );
349 
350 		return( -1 );
351 	}
352 	/* Make sure libvslvm logical volume is set to NULL
353 	 */
354 	pyvslvm_logical_volume->logical_volume = NULL;
355 
356 	return( 0 );
357 }
358 
359 /* Frees a logical volume object
360  */
pyvslvm_logical_volume_free(pyvslvm_logical_volume_t * pyvslvm_logical_volume)361 void pyvslvm_logical_volume_free(
362       pyvslvm_logical_volume_t *pyvslvm_logical_volume )
363 {
364 	libcerror_error_t *error    = NULL;
365 	struct _typeobject *ob_type = NULL;
366 	static char *function       = "pyvslvm_logical_volume_free";
367 
368 	if( pyvslvm_logical_volume == NULL )
369 	{
370 		PyErr_Format(
371 		 PyExc_TypeError,
372 		 "%s: invalid logical volume.",
373 		 function );
374 
375 		return;
376 	}
377 	if( pyvslvm_logical_volume->logical_volume == NULL )
378 	{
379 		PyErr_Format(
380 		 PyExc_TypeError,
381 		 "%s: invalid logical volume - missing libvslvm logical volume.",
382 		 function );
383 
384 		return;
385 	}
386 	ob_type = Py_TYPE(
387 	           pyvslvm_logical_volume );
388 
389 	if( ob_type == NULL )
390 	{
391 		PyErr_Format(
392 		 PyExc_ValueError,
393 		 "%s: missing ob_type.",
394 		 function );
395 
396 		return;
397 	}
398 	if( ob_type->tp_free == NULL )
399 	{
400 		PyErr_Format(
401 		 PyExc_ValueError,
402 		 "%s: invalid ob_type - missing tp_free.",
403 		 function );
404 
405 		return;
406 	}
407 	if( libvslvm_logical_volume_free(
408 	     &( pyvslvm_logical_volume->logical_volume ),
409 	     &error ) != 1 )
410 	{
411 		pyvslvm_error_raise(
412 		 error,
413 		 PyExc_IOError,
414 		 "%s: unable to free libvslvm logical volume.",
415 		 function );
416 
417 		libcerror_error_free(
418 		 &error );
419 	}
420 	if( pyvslvm_logical_volume->volume_group_object != NULL )
421 	{
422 		Py_DecRef(
423 		 (PyObject *) pyvslvm_logical_volume->volume_group_object );
424 	}
425 	ob_type->tp_free(
426 	 (PyObject*) pyvslvm_logical_volume );
427 }
428 
429 /* Reads data at the current offset into a buffer
430  * Returns a Python object if successful or NULL on error
431  */
pyvslvm_logical_volume_read_buffer(pyvslvm_logical_volume_t * pyvslvm_logical_volume,PyObject * arguments,PyObject * keywords)432 PyObject *pyvslvm_logical_volume_read_buffer(
433            pyvslvm_logical_volume_t *pyvslvm_logical_volume,
434            PyObject *arguments,
435            PyObject *keywords )
436 {
437 	libcerror_error_t *error    = NULL;
438 	PyObject *string_object     = NULL;
439 	static char *function       = "pyvslvm_logical_volume_read_buffer";
440 	static char *keyword_list[] = { "size", NULL };
441 	char *buffer                = NULL;
442 	ssize_t read_count          = 0;
443 	int read_size               = -1;
444 
445 	if( pyvslvm_logical_volume == NULL )
446 	{
447 		PyErr_Format(
448 		 PyExc_TypeError,
449 		 "%s: invalid pyvslvm logical volume.",
450 		 function );
451 
452 		return( NULL );
453 	}
454 	if( PyArg_ParseTupleAndKeywords(
455 	     arguments,
456 	     keywords,
457 	     "|i",
458 	     keyword_list,
459 	     &read_size ) == 0 )
460 	{
461 		return( NULL );
462 	}
463 	if( read_size < 0 )
464 	{
465 		PyErr_Format(
466 		 PyExc_ValueError,
467 		 "%s: invalid argument read size value less than zero.",
468 		 function );
469 
470 		return( NULL );
471 	}
472 	/* Make sure the data fits into the memory buffer
473 	 */
474 	if( read_size > INT_MAX )
475 	{
476 		PyErr_Format(
477 		 PyExc_ValueError,
478 		 "%s: invalid argument read size value exceeds maximum.",
479 		 function );
480 
481 		return( NULL );
482 	}
483 #if PY_MAJOR_VERSION >= 3
484 	string_object = PyBytes_FromStringAndSize(
485 	                 NULL,
486 	                 read_size );
487 
488 	buffer = PyBytes_AsString(
489 	          string_object );
490 #else
491 	string_object = PyString_FromStringAndSize(
492 	                 NULL,
493 	                 read_size );
494 
495 	buffer = PyString_AsString(
496 	          string_object );
497 #endif
498 	Py_BEGIN_ALLOW_THREADS
499 
500 	read_count = libvslvm_logical_volume_read_buffer(
501 	              pyvslvm_logical_volume->logical_volume,
502 	              (uint8_t *) buffer,
503 	              (size_t) read_size,
504 	              &error );
505 
506 	Py_END_ALLOW_THREADS
507 
508 	if( read_count <= -1 )
509 	{
510 		pyvslvm_error_raise(
511 		 error,
512 		 PyExc_IOError,
513 		 "%s: unable to read data.",
514 		 function );
515 
516 		libcerror_error_free(
517 		 &error );
518 
519 		Py_DecRef(
520 		 (PyObject *) string_object );
521 
522 		return( NULL );
523 	}
524 	/* Need to resize the string here in case read_size was not fully read.
525 	 */
526 #if PY_MAJOR_VERSION >= 3
527 	if( _PyBytes_Resize(
528 	     &string_object,
529 	     (Py_ssize_t) read_count ) != 0 )
530 #else
531 	if( _PyString_Resize(
532 	     &string_object,
533 	     (Py_ssize_t) read_count ) != 0 )
534 #endif
535 	{
536 		Py_DecRef(
537 		 (PyObject *) string_object );
538 
539 		return( NULL );
540 	}
541 	return( string_object );
542 }
543 
544 /* Reads data at a specific offset
545  * Returns a Python object if successful or NULL on error
546  */
pyvslvm_logical_volume_read_buffer_at_offset(pyvslvm_logical_volume_t * pyvslvm_logical_volume,PyObject * arguments,PyObject * keywords)547 PyObject *pyvslvm_logical_volume_read_buffer_at_offset(
548            pyvslvm_logical_volume_t *pyvslvm_logical_volume,
549            PyObject *arguments,
550            PyObject *keywords )
551 {
552 	libcerror_error_t *error    = NULL;
553 	PyObject *string_object     = NULL;
554 	static char *function       = "pyvslvm_logical_volume_read_buffer_at_offset";
555 	static char *keyword_list[] = { "size", "offset", NULL };
556 	char *buffer                = NULL;
557 	off64_t read_offset         = 0;
558 	ssize_t read_count          = 0;
559 	int read_size               = 0;
560 
561 	if( pyvslvm_logical_volume == NULL )
562 	{
563 		PyErr_Format(
564 		 PyExc_TypeError,
565 		 "%s: invalid pyvslvm logical volume.",
566 		 function );
567 
568 		return( NULL );
569 	}
570 	if( PyArg_ParseTupleAndKeywords(
571 	     arguments,
572 	     keywords,
573 	     "i|L",
574 	     keyword_list,
575 	     &read_size,
576 	     &read_offset ) == 0 )
577 	{
578 		return( NULL );
579 	}
580 	if( read_size < 0 )
581 	{
582 		PyErr_Format(
583 		 PyExc_ValueError,
584 		 "%s: invalid argument read size value less than zero.",
585 		 function );
586 
587 		return( NULL );
588 	}
589 	/* Make sure the data fits into the memory buffer
590 	 */
591 	if( read_size > INT_MAX )
592 	{
593 		PyErr_Format(
594 		 PyExc_ValueError,
595 		 "%s: invalid argument read size value exceeds maximum.",
596 		 function );
597 
598 		return( NULL );
599 	}
600 	if( read_offset < 0 )
601 	{
602 		PyErr_Format(
603 		 PyExc_ValueError,
604 		 "%s: invalid argument read offset value less than zero.",
605 		 function );
606 
607 		return( NULL );
608 	}
609 	/* Make sure the data fits into the memory buffer
610 	 */
611 #if PY_MAJOR_VERSION >= 3
612 	string_object = PyBytes_FromStringAndSize(
613 	                 NULL,
614 	                 read_size );
615 
616 	buffer = PyBytes_AsString(
617 	          string_object );
618 #else
619 	string_object = PyString_FromStringAndSize(
620 	                 NULL,
621 	                 read_size );
622 
623 	buffer = PyString_AsString(
624 	          string_object );
625 #endif
626 	Py_BEGIN_ALLOW_THREADS
627 
628 	read_count = libvslvm_logical_volume_read_buffer_at_offset(
629 	              pyvslvm_logical_volume->logical_volume,
630 	              (uint8_t *) buffer,
631 	              (size_t) read_size,
632 	              (off64_t) read_offset,
633 	              &error );
634 
635 	Py_END_ALLOW_THREADS
636 
637 	if( read_count <= -1 )
638 	{
639 		pyvslvm_error_raise(
640 		 error,
641 		 PyExc_IOError,
642 		 "%s: unable to read data.",
643 		 function );
644 
645 		libcerror_error_free(
646 		 &error );
647 
648 		Py_DecRef(
649 		 (PyObject *) string_object );
650 
651 		return( NULL );
652 	}
653 	/* Need to resize the string here in case read_size was not fully read.
654 	 */
655 #if PY_MAJOR_VERSION >= 3
656 	if( _PyBytes_Resize(
657 	     &string_object,
658 	     (Py_ssize_t) read_count ) != 0 )
659 #else
660 	if( _PyString_Resize(
661 	     &string_object,
662 	     (Py_ssize_t) read_count ) != 0 )
663 #endif
664 	{
665 		Py_DecRef(
666 		 (PyObject *) string_object );
667 
668 		return( NULL );
669 	}
670 	return( string_object );
671 }
672 
673 /* Seeks a certain offset in the data
674  * Returns a Python object if successful or NULL on error
675  */
pyvslvm_logical_volume_seek_offset(pyvslvm_logical_volume_t * pyvslvm_logical_volume,PyObject * arguments,PyObject * keywords)676 PyObject *pyvslvm_logical_volume_seek_offset(
677            pyvslvm_logical_volume_t *pyvslvm_logical_volume,
678            PyObject *arguments,
679            PyObject *keywords )
680 {
681 	libcerror_error_t *error    = NULL;
682 	static char *function       = "pyvslvm_logical_volume_seek_offset";
683 	static char *keyword_list[] = { "offset", "whence", NULL };
684 	off64_t offset              = 0;
685 	int whence                  = 0;
686 
687 	if( pyvslvm_logical_volume == NULL )
688 	{
689 		PyErr_Format(
690 		 PyExc_TypeError,
691 		 "%s: invalid pyvslvm logical volume.",
692 		 function );
693 
694 		return( NULL );
695 	}
696 	if( PyArg_ParseTupleAndKeywords(
697 	     arguments,
698 	     keywords,
699 	     "L|i",
700 	     keyword_list,
701 	     &offset,
702 	     &whence ) == 0 )
703 	{
704 		return( NULL );
705 	}
706 	Py_BEGIN_ALLOW_THREADS
707 
708 	offset = libvslvm_logical_volume_seek_offset(
709 	          pyvslvm_logical_volume->logical_volume,
710 	          offset,
711 	          whence,
712 	          &error );
713 
714 	Py_END_ALLOW_THREADS
715 
716  	if( offset == -1 )
717 	{
718 		pyvslvm_error_raise(
719 		 error,
720 		 PyExc_IOError,
721 		 "%s: unable to seek offset.",
722 		 function );
723 
724 		libcerror_error_free(
725 		 &error );
726 
727 		return( NULL );
728 	}
729 	Py_IncRef(
730 	 Py_None );
731 
732 	return( Py_None );
733 }
734 
735 /* Retrieves the current offset in the data
736  * Returns a Python object if successful or NULL on error
737  */
pyvslvm_logical_volume_get_offset(pyvslvm_logical_volume_t * pyvslvm_logical_volume,PyObject * arguments PYVSLVM_ATTRIBUTE_UNUSED)738 PyObject *pyvslvm_logical_volume_get_offset(
739            pyvslvm_logical_volume_t *pyvslvm_logical_volume,
740            PyObject *arguments PYVSLVM_ATTRIBUTE_UNUSED )
741 {
742 	libcerror_error_t *error = NULL;
743 	PyObject *integer_object = NULL;
744 	static char *function    = "pyvslvm_logical_volume_get_offset";
745 	off64_t current_offset   = 0;
746 	int result               = 0;
747 
748 	PYVSLVM_UNREFERENCED_PARAMETER( arguments )
749 
750 	if( pyvslvm_logical_volume == NULL )
751 	{
752 		PyErr_Format(
753 		 PyExc_TypeError,
754 		 "%s: invalid logical volume.",
755 		 function );
756 
757 		return( NULL );
758 	}
759 	Py_BEGIN_ALLOW_THREADS
760 
761 	result = libvslvm_logical_volume_get_offset(
762 	          pyvslvm_logical_volume->logical_volume,
763 	          &current_offset,
764 	          &error );
765 
766 	Py_END_ALLOW_THREADS
767 
768 	if( result != 1 )
769 	{
770 		pyvslvm_error_raise(
771 		 error,
772 		 PyExc_IOError,
773 		 "%s: unable to retrieve offset.",
774 		 function );
775 
776 		libcerror_error_free(
777 		 &error );
778 
779 		return( NULL );
780 	}
781 	integer_object = pyvslvm_integer_signed_new_from_64bit(
782 	                  (int64_t) current_offset );
783 
784 	return( integer_object );
785 }
786 
787 /* Retrieves the size
788  * Returns a Python object if successful or NULL on error
789  */
pyvslvm_logical_volume_get_size(pyvslvm_logical_volume_t * pyvslvm_logical_volume,PyObject * arguments PYVSLVM_ATTRIBUTE_UNUSED)790 PyObject *pyvslvm_logical_volume_get_size(
791            pyvslvm_logical_volume_t *pyvslvm_logical_volume,
792            PyObject *arguments PYVSLVM_ATTRIBUTE_UNUSED )
793 {
794 	libcerror_error_t *error = NULL;
795 	PyObject *integer_object = NULL;
796 	static char *function    = "pyvslvm_logical_volume_get_size";
797 	size64_t size            = 0;
798 	int result               = 0;
799 
800 	PYVSLVM_UNREFERENCED_PARAMETER( arguments )
801 
802 	if( pyvslvm_logical_volume == NULL )
803 	{
804 		PyErr_Format(
805 		 PyExc_TypeError,
806 		 "%s: invalid logical volume.",
807 		 function );
808 
809 		return( NULL );
810 	}
811 	Py_BEGIN_ALLOW_THREADS
812 
813 	result = libvslvm_logical_volume_get_size(
814 	          pyvslvm_logical_volume->logical_volume,
815 	          &size,
816 	          &error );
817 
818 	Py_END_ALLOW_THREADS
819 
820 	if( result != 1 )
821 	{
822 		pyvslvm_error_raise(
823 		 error,
824 		 PyExc_IOError,
825 		 "%s: failed to retrieve size.",
826 		 function );
827 
828 		libcerror_error_free(
829 		 &error );
830 
831 		return( NULL );
832 	}
833 	integer_object = pyvslvm_integer_unsigned_new_from_64bit(
834 	                  (uint64_t) size );
835 
836 	return( integer_object );
837 }
838 
839 /* Retrieves the name
840  * Returns a Python object if successful or NULL on error
841  */
pyvslvm_logical_volume_get_name(pyvslvm_logical_volume_t * pyvslvm_logical_volume,PyObject * arguments PYVSLVM_ATTRIBUTE_UNUSED)842 PyObject *pyvslvm_logical_volume_get_name(
843            pyvslvm_logical_volume_t *pyvslvm_logical_volume,
844            PyObject *arguments PYVSLVM_ATTRIBUTE_UNUSED )
845 {
846 	libcerror_error_t *error = NULL;
847 	PyObject *string_object  = NULL;
848 	char *name               = NULL;
849 	const char *errors       = NULL;
850 	static char *function    = "pyvslvm_logical_volume_get_name";
851 	size_t name_size         = 0;
852 	int result               = 0;
853 
854 	PYVSLVM_UNREFERENCED_PARAMETER( arguments )
855 
856 	if( pyvslvm_logical_volume == NULL )
857 	{
858 		PyErr_Format(
859 		 PyExc_TypeError,
860 		 "%s: invalid logical volume.",
861 		 function );
862 
863 		return( NULL );
864 	}
865 	Py_BEGIN_ALLOW_THREADS
866 
867 	result = libvslvm_logical_volume_get_name_size(
868 	          pyvslvm_logical_volume->logical_volume,
869 	          &name_size,
870 	          &error );
871 
872 	Py_END_ALLOW_THREADS
873 
874 	if( result == -1 )
875 	{
876 		pyvslvm_error_raise(
877 		 error,
878 		 PyExc_IOError,
879 		 "%s: unable to retrieve name size.",
880 		 function );
881 
882 		libcerror_error_free(
883 		 &error );
884 
885 		goto on_error;
886 	}
887 	else if( ( result == 0 )
888 	      || ( name_size == 0 ) )
889 	{
890 		Py_IncRef(
891 		 Py_None );
892 
893 		return( Py_None );
894 	}
895 	name = (char *) PyMem_Malloc(
896 	                 sizeof( char ) * name_size );
897 
898 	if( name == NULL )
899 	{
900 		PyErr_Format(
901 		 PyExc_IOError,
902 		 "%s: unable to create name.",
903 		 function );
904 
905 		goto on_error;
906 	}
907 	Py_BEGIN_ALLOW_THREADS
908 
909 	result = libvslvm_logical_volume_get_name(
910 		  pyvslvm_logical_volume->logical_volume,
911 		  name,
912 		  name_size,
913 		  &error );
914 
915 	Py_END_ALLOW_THREADS
916 
917 	if( result != 1 )
918 	{
919 		pyvslvm_error_raise(
920 		 error,
921 		 PyExc_IOError,
922 		 "%s: unable to retrieve name.",
923 		 function );
924 
925 		libcerror_error_free(
926 		 &error );
927 
928 		goto on_error;
929 	}
930 	/* Pass the string length to PyUnicode_DecodeUTF8
931 	 * otherwise it makes the end of string character is part
932 	 * of the string
933 	 */
934 	string_object = PyUnicode_DecodeUTF8(
935 			 name,
936 			 (Py_ssize_t) name_size - 1,
937 			 errors );
938 
939 	PyMem_Free(
940 	 name );
941 
942 	return( string_object );
943 
944 on_error:
945 	if( name != NULL )
946 	{
947 		PyMem_Free(
948 		 name );
949 	}
950 	return( NULL );
951 }
952 
953 /* Retrieves the identifier
954  * Returns a Python object if successful or NULL on error
955  */
pyvslvm_logical_volume_get_identifier(pyvslvm_logical_volume_t * pyvslvm_logical_volume,PyObject * arguments PYVSLVM_ATTRIBUTE_UNUSED)956 PyObject *pyvslvm_logical_volume_get_identifier(
957            pyvslvm_logical_volume_t *pyvslvm_logical_volume,
958            PyObject *arguments PYVSLVM_ATTRIBUTE_UNUSED )
959 {
960 	libcerror_error_t *error = NULL;
961 	PyObject *string_object  = NULL;
962 	char *identifier         = NULL;
963 	const char *errors       = NULL;
964 	static char *function    = "pyvslvm_logical_volume_get_identifier";
965 	size_t identifier_size   = 0;
966 	int result               = 0;
967 
968 	PYVSLVM_UNREFERENCED_PARAMETER( arguments )
969 
970 	if( pyvslvm_logical_volume == NULL )
971 	{
972 		PyErr_Format(
973 		 PyExc_TypeError,
974 		 "%s: invalid logical volume.",
975 		 function );
976 
977 		return( NULL );
978 	}
979 	Py_BEGIN_ALLOW_THREADS
980 
981 	result = libvslvm_logical_volume_get_identifier_size(
982 	          pyvslvm_logical_volume->logical_volume,
983 	          &identifier_size,
984 	          &error );
985 
986 	Py_END_ALLOW_THREADS
987 
988 	if( result == -1 )
989 	{
990 		pyvslvm_error_raise(
991 		 error,
992 		 PyExc_IOError,
993 		 "%s: unable to retrieve identifier size.",
994 		 function );
995 
996 		libcerror_error_free(
997 		 &error );
998 
999 		goto on_error;
1000 	}
1001 	else if( ( result == 0 )
1002 	      || ( identifier_size == 0 ) )
1003 	{
1004 		Py_IncRef(
1005 		 Py_None );
1006 
1007 		return( Py_None );
1008 	}
1009 	identifier = (char *) PyMem_Malloc(
1010 	                       sizeof( char ) * identifier_size );
1011 
1012 	if( identifier == NULL )
1013 	{
1014 		PyErr_Format(
1015 		 PyExc_IOError,
1016 		 "%s: unable to create identifier.",
1017 		 function );
1018 
1019 		goto on_error;
1020 	}
1021 	Py_BEGIN_ALLOW_THREADS
1022 
1023 	result = libvslvm_logical_volume_get_identifier(
1024 		  pyvslvm_logical_volume->logical_volume,
1025 		  identifier,
1026 		  identifier_size,
1027 		  &error );
1028 
1029 	Py_END_ALLOW_THREADS
1030 
1031 	if( result != 1 )
1032 	{
1033 		pyvslvm_error_raise(
1034 		 error,
1035 		 PyExc_IOError,
1036 		 "%s: unable to retrieve identifier.",
1037 		 function );
1038 
1039 		libcerror_error_free(
1040 		 &error );
1041 
1042 		goto on_error;
1043 	}
1044 	/* Pass the string length to PyUnicode_DecodeUTF8
1045 	 * otherwise it makes the end of string character is part
1046 	 * of the string
1047 	 */
1048 	string_object = PyUnicode_DecodeUTF8(
1049 			 identifier,
1050 			 (Py_ssize_t) identifier_size - 1,
1051 			 errors );
1052 
1053 	PyMem_Free(
1054 	 identifier );
1055 
1056 	return( string_object );
1057 
1058 on_error:
1059 	if( identifier != NULL )
1060 	{
1061 		PyMem_Free(
1062 		 identifier );
1063 	}
1064 	return( NULL );
1065 }
1066 
1067 /* Retrieves the number of segments
1068  * Returns a Python object if successful or NULL on error
1069  */
pyvslvm_logical_volume_get_number_of_segments(pyvslvm_logical_volume_t * pyvslvm_logical_volume,PyObject * arguments PYVSLVM_ATTRIBUTE_UNUSED)1070 PyObject *pyvslvm_logical_volume_get_number_of_segments(
1071            pyvslvm_logical_volume_t *pyvslvm_logical_volume,
1072            PyObject *arguments PYVSLVM_ATTRIBUTE_UNUSED )
1073 {
1074 	libcerror_error_t *error = NULL;
1075 	PyObject *integer_object = NULL;
1076 	static char *function    = "pyvslvm_logical_volume_get_number_of_segments";
1077 	int number_of_segments   = 0;
1078 	int result               = 0;
1079 
1080 	PYVSLVM_UNREFERENCED_PARAMETER( arguments )
1081 
1082 	if( pyvslvm_logical_volume == NULL )
1083 	{
1084 		PyErr_Format(
1085 		 PyExc_TypeError,
1086 		 "%s: invalid logical volume.",
1087 		 function );
1088 
1089 		return( NULL );
1090 	}
1091 	Py_BEGIN_ALLOW_THREADS
1092 
1093 	result = libvslvm_logical_volume_get_number_of_segments(
1094 	          pyvslvm_logical_volume->logical_volume,
1095 	          &number_of_segments,
1096 	          &error );
1097 
1098 	Py_END_ALLOW_THREADS
1099 
1100 	if( result != 1 )
1101 	{
1102 		pyvslvm_error_raise(
1103 		 error,
1104 		 PyExc_IOError,
1105 		 "%s: unable to retrieve number of segments.",
1106 		 function );
1107 
1108 		libcerror_error_free(
1109 		 &error );
1110 
1111 		return( NULL );
1112 	}
1113 #if PY_MAJOR_VERSION >= 3
1114 	integer_object = PyLong_FromLong(
1115 	                  (long) number_of_segments );
1116 #else
1117 	integer_object = PyInt_FromLong(
1118 	                  (long) number_of_segments );
1119 #endif
1120 	return( integer_object );
1121 }
1122 
1123 /* Retrieves a specific segment by index
1124  * Returns a Python object if successful or NULL on error
1125  */
pyvslvm_logical_volume_get_segment_by_index(PyObject * pyvslvm_logical_volume,int segment_index)1126 PyObject *pyvslvm_logical_volume_get_segment_by_index(
1127            PyObject *pyvslvm_logical_volume,
1128            int segment_index )
1129 {
1130 	libcerror_error_t *error    = NULL;
1131 	libvslvm_segment_t *segment = NULL;
1132 	PyObject *segment_object    = NULL;
1133 	static char *function       = "pyvslvm_logical_volume_get_segment_by_index";
1134 	int result                  = 0;
1135 
1136 	if( pyvslvm_logical_volume == NULL )
1137 	{
1138 		PyErr_Format(
1139 		 PyExc_TypeError,
1140 		 "%s: invalid logical volume.",
1141 		 function );
1142 
1143 		return( NULL );
1144 	}
1145 	Py_BEGIN_ALLOW_THREADS
1146 
1147 	result = libvslvm_logical_volume_get_segment(
1148 	          ( (pyvslvm_logical_volume_t *) pyvslvm_logical_volume )->logical_volume,
1149 	          segment_index,
1150 	          &segment,
1151 	          &error );
1152 
1153 	Py_END_ALLOW_THREADS
1154 
1155 	if( result != 1 )
1156 	{
1157 		pyvslvm_error_raise(
1158 		 error,
1159 		 PyExc_IOError,
1160 		 "%s: unable to retrieve segment: %d.",
1161 		 function,
1162 		 segment_index );
1163 
1164 		libcerror_error_free(
1165 		 &error );
1166 
1167 		goto on_error;
1168 	}
1169 	segment_object = pyvslvm_segment_new(
1170 	                  segment,
1171 	                  (pyvslvm_logical_volume_t *) pyvslvm_logical_volume );
1172 
1173 	if( segment_object == NULL )
1174 	{
1175 		PyErr_Format(
1176 		 PyExc_MemoryError,
1177 		 "%s: unable to create segment object.",
1178 		 function );
1179 
1180 		goto on_error;
1181 	}
1182 	return( segment_object );
1183 
1184 on_error:
1185 	if( segment != NULL )
1186 	{
1187 		libvslvm_segment_free(
1188 		 &segment,
1189 		 NULL );
1190 	}
1191 	return( NULL );
1192 }
1193 
1194 /* Retrieves a specific segment
1195  * Returns a Python object if successful or NULL on error
1196  */
pyvslvm_logical_volume_get_segment(pyvslvm_logical_volume_t * pyvslvm_logical_volume,PyObject * arguments,PyObject * keywords)1197 PyObject *pyvslvm_logical_volume_get_segment(
1198            pyvslvm_logical_volume_t *pyvslvm_logical_volume,
1199            PyObject *arguments,
1200            PyObject *keywords )
1201 {
1202 	PyObject *segment_object    = NULL;
1203 	static char *keyword_list[] = { "segment_index", NULL };
1204 	int segment_index           = 0;
1205 
1206 	if( PyArg_ParseTupleAndKeywords(
1207 	     arguments,
1208 	     keywords,
1209 	     "i",
1210 	     keyword_list,
1211 	     &segment_index ) == 0 )
1212 	{
1213 		return( NULL );
1214 	}
1215 	segment_object = pyvslvm_logical_volume_get_segment_by_index(
1216 	                  (PyObject *) pyvslvm_logical_volume,
1217 	                  segment_index );
1218 
1219 	return( segment_object );
1220 }
1221 
1222 /* Retrieves a segments sequence and iterator object for the segments
1223  * Returns a Python object if successful or NULL on error
1224  */
pyvslvm_logical_volume_get_segments(pyvslvm_logical_volume_t * pyvslvm_logical_volume,PyObject * arguments PYVSLVM_ATTRIBUTE_UNUSED)1225 PyObject *pyvslvm_logical_volume_get_segments(
1226            pyvslvm_logical_volume_t *pyvslvm_logical_volume,
1227            PyObject *arguments PYVSLVM_ATTRIBUTE_UNUSED )
1228 {
1229 	libcerror_error_t *error  = NULL;
1230 	PyObject *segments_object = NULL;
1231 	static char *function     = "pyvslvm_logical_volume_get_segments";
1232 	int number_of_segments    = 0;
1233 	int result                = 0;
1234 
1235 	PYVSLVM_UNREFERENCED_PARAMETER( arguments )
1236 
1237 	if( pyvslvm_logical_volume == NULL )
1238 	{
1239 		PyErr_Format(
1240 		 PyExc_TypeError,
1241 		 "%s: invalid logical volume.",
1242 		 function );
1243 
1244 		return( NULL );
1245 	}
1246 	Py_BEGIN_ALLOW_THREADS
1247 
1248 	result = libvslvm_logical_volume_get_number_of_segments(
1249 	          pyvslvm_logical_volume->logical_volume,
1250 	          &number_of_segments,
1251 	          &error );
1252 
1253 	Py_END_ALLOW_THREADS
1254 
1255 	if( result != 1 )
1256 	{
1257 		pyvslvm_error_raise(
1258 		 error,
1259 		 PyExc_IOError,
1260 		 "%s: unable to retrieve number of segments.",
1261 		 function );
1262 
1263 		libcerror_error_free(
1264 		 &error );
1265 
1266 		return( NULL );
1267 	}
1268 	segments_object = pyvslvm_segments_new(
1269 	                   (PyObject *) pyvslvm_logical_volume,
1270 	                   &pyvslvm_logical_volume_get_segment_by_index,
1271 	                   number_of_segments );
1272 
1273 	if( segments_object == NULL )
1274 	{
1275 		PyErr_Format(
1276 		 PyExc_MemoryError,
1277 		 "%s: unable to create segments object.",
1278 		 function );
1279 
1280 		return( NULL );
1281 	}
1282 	return( segments_object );
1283 }
1284 
1285