1 /*
2 * Python object definition of the sequence and iterator object of volumes
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_libcerror.h"
30 #include "pyfsapfs_libfsapfs.h"
31 #include "pyfsapfs_python.h"
32 #include "pyfsapfs_volume.h"
33 #include "pyfsapfs_volumes.h"
34
35 PySequenceMethods pyfsapfs_volumes_sequence_methods = {
36 /* sq_length */
37 (lenfunc) pyfsapfs_volumes_len,
38 /* sq_concat */
39 0,
40 /* sq_repeat */
41 0,
42 /* sq_item */
43 (ssizeargfunc) pyfsapfs_volumes_getitem,
44 /* sq_slice */
45 0,
46 /* sq_ass_item */
47 0,
48 /* sq_ass_slice */
49 0,
50 /* sq_contains */
51 0,
52 /* sq_inplace_concat */
53 0,
54 /* sq_inplace_repeat */
55 0
56 };
57
58 PyTypeObject pyfsapfs_volumes_type_object = {
59 PyVarObject_HEAD_INIT( NULL, 0 )
60
61 /* tp_name */
62 "pyfsapfs.volumes",
63 /* tp_basicsize */
64 sizeof( pyfsapfs_volumes_t ),
65 /* tp_itemsize */
66 0,
67 /* tp_dealloc */
68 (destructor) pyfsapfs_volumes_free,
69 /* tp_print */
70 0,
71 /* tp_getattr */
72 0,
73 /* tp_setattr */
74 0,
75 /* tp_compare */
76 0,
77 /* tp_repr */
78 0,
79 /* tp_as_number */
80 0,
81 /* tp_as_sequence */
82 &pyfsapfs_volumes_sequence_methods,
83 /* tp_as_mapping */
84 0,
85 /* tp_hash */
86 0,
87 /* tp_call */
88 0,
89 /* tp_str */
90 0,
91 /* tp_getattro */
92 0,
93 /* tp_setattro */
94 0,
95 /* tp_as_buffer */
96 0,
97 /* tp_flags */
98 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,
99 /* tp_doc */
100 "pyfsapfs sequence and iterator object of volumes",
101 /* tp_traverse */
102 0,
103 /* tp_clear */
104 0,
105 /* tp_richcompare */
106 0,
107 /* tp_weaklistoffset */
108 0,
109 /* tp_iter */
110 (getiterfunc) pyfsapfs_volumes_iter,
111 /* tp_iternext */
112 (iternextfunc) pyfsapfs_volumes_iternext,
113 /* tp_methods */
114 0,
115 /* tp_members */
116 0,
117 /* tp_getset */
118 0,
119 /* tp_base */
120 0,
121 /* tp_dict */
122 0,
123 /* tp_descr_get */
124 0,
125 /* tp_descr_set */
126 0,
127 /* tp_dictoffset */
128 0,
129 /* tp_init */
130 (initproc) pyfsapfs_volumes_init,
131 /* tp_alloc */
132 0,
133 /* tp_new */
134 0,
135 /* tp_free */
136 0,
137 /* tp_is_gc */
138 0,
139 /* tp_bases */
140 NULL,
141 /* tp_mro */
142 NULL,
143 /* tp_cache */
144 NULL,
145 /* tp_subclasses */
146 NULL,
147 /* tp_weaklist */
148 NULL,
149 /* tp_del */
150 0
151 };
152
153 /* Creates a new volumes sequence and iterator object
154 * Returns a Python object if successful or NULL on error
155 */
pyfsapfs_volumes_new(PyObject * parent_object,PyObject * (* get_item_by_index)(PyObject * parent_object,int index),int number_of_items)156 PyObject *pyfsapfs_volumes_new(
157 PyObject *parent_object,
158 PyObject* (*get_item_by_index)(
159 PyObject *parent_object,
160 int index ),
161 int number_of_items )
162 {
163 pyfsapfs_volumes_t *sequence_object = NULL;
164 static char *function = "pyfsapfs_volumes_new";
165
166 if( parent_object == NULL )
167 {
168 PyErr_Format(
169 PyExc_ValueError,
170 "%s: invalid parent object.",
171 function );
172
173 return( NULL );
174 }
175 if( get_item_by_index == NULL )
176 {
177 PyErr_Format(
178 PyExc_ValueError,
179 "%s: invalid get item by index function.",
180 function );
181
182 return( NULL );
183 }
184 /* Make sure the volumes values are initialized
185 */
186 sequence_object = PyObject_New(
187 struct pyfsapfs_volumes,
188 &pyfsapfs_volumes_type_object );
189
190 if( sequence_object == NULL )
191 {
192 PyErr_Format(
193 PyExc_MemoryError,
194 "%s: unable to create sequence object.",
195 function );
196
197 goto on_error;
198 }
199 sequence_object->parent_object = parent_object;
200 sequence_object->get_item_by_index = get_item_by_index;
201 sequence_object->current_index = 0;
202 sequence_object->number_of_items = number_of_items;
203
204 Py_IncRef(
205 (PyObject *) sequence_object->parent_object );
206
207 return( (PyObject *) sequence_object );
208
209 on_error:
210 if( sequence_object != NULL )
211 {
212 Py_DecRef(
213 (PyObject *) sequence_object );
214 }
215 return( NULL );
216 }
217
218 /* Initializes a volumes sequence and iterator object
219 * Returns 0 if successful or -1 on error
220 */
pyfsapfs_volumes_init(pyfsapfs_volumes_t * sequence_object)221 int pyfsapfs_volumes_init(
222 pyfsapfs_volumes_t *sequence_object )
223 {
224 static char *function = "pyfsapfs_volumes_init";
225
226 if( sequence_object == NULL )
227 {
228 PyErr_Format(
229 PyExc_ValueError,
230 "%s: invalid sequence object.",
231 function );
232
233 return( -1 );
234 }
235 /* Make sure the volumes values are initialized
236 */
237 sequence_object->parent_object = NULL;
238 sequence_object->get_item_by_index = NULL;
239 sequence_object->current_index = 0;
240 sequence_object->number_of_items = 0;
241
242 PyErr_Format(
243 PyExc_NotImplementedError,
244 "%s: initialize of volumes not supported.",
245 function );
246
247 return( -1 );
248 }
249
250 /* Frees a volumes sequence object
251 */
pyfsapfs_volumes_free(pyfsapfs_volumes_t * sequence_object)252 void pyfsapfs_volumes_free(
253 pyfsapfs_volumes_t *sequence_object )
254 {
255 struct _typeobject *ob_type = NULL;
256 static char *function = "pyfsapfs_volumes_free";
257
258 if( sequence_object == NULL )
259 {
260 PyErr_Format(
261 PyExc_ValueError,
262 "%s: invalid sequence object.",
263 function );
264
265 return;
266 }
267 ob_type = Py_TYPE(
268 sequence_object );
269
270 if( ob_type == NULL )
271 {
272 PyErr_Format(
273 PyExc_ValueError,
274 "%s: missing ob_type.",
275 function );
276
277 return;
278 }
279 if( ob_type->tp_free == NULL )
280 {
281 PyErr_Format(
282 PyExc_ValueError,
283 "%s: invalid ob_type - missing tp_free.",
284 function );
285
286 return;
287 }
288 if( sequence_object->parent_object != NULL )
289 {
290 Py_DecRef(
291 (PyObject *) sequence_object->parent_object );
292 }
293 ob_type->tp_free(
294 (PyObject*) sequence_object );
295 }
296
297 /* The volumes len() function
298 */
pyfsapfs_volumes_len(pyfsapfs_volumes_t * sequence_object)299 Py_ssize_t pyfsapfs_volumes_len(
300 pyfsapfs_volumes_t *sequence_object )
301 {
302 static char *function = "pyfsapfs_volumes_len";
303
304 if( sequence_object == NULL )
305 {
306 PyErr_Format(
307 PyExc_ValueError,
308 "%s: invalid sequence object.",
309 function );
310
311 return( -1 );
312 }
313 return( (Py_ssize_t) sequence_object->number_of_items );
314 }
315
316 /* The volumes getitem() function
317 */
pyfsapfs_volumes_getitem(pyfsapfs_volumes_t * sequence_object,Py_ssize_t item_index)318 PyObject *pyfsapfs_volumes_getitem(
319 pyfsapfs_volumes_t *sequence_object,
320 Py_ssize_t item_index )
321 {
322 PyObject *volume_object = NULL;
323 static char *function = "pyfsapfs_volumes_getitem";
324
325 if( sequence_object == NULL )
326 {
327 PyErr_Format(
328 PyExc_ValueError,
329 "%s: invalid sequence object.",
330 function );
331
332 return( NULL );
333 }
334 if( sequence_object->get_item_by_index == NULL )
335 {
336 PyErr_Format(
337 PyExc_ValueError,
338 "%s: invalid sequence object - missing get item by index function.",
339 function );
340
341 return( NULL );
342 }
343 if( sequence_object->number_of_items < 0 )
344 {
345 PyErr_Format(
346 PyExc_ValueError,
347 "%s: invalid sequence object - invalid number of items.",
348 function );
349
350 return( NULL );
351 }
352 if( ( item_index < 0 )
353 || ( item_index >= (Py_ssize_t) sequence_object->number_of_items ) )
354 {
355 PyErr_Format(
356 PyExc_ValueError,
357 "%s: invalid invalid item index value out of bounds.",
358 function );
359
360 return( NULL );
361 }
362 volume_object = sequence_object->get_item_by_index(
363 sequence_object->parent_object,
364 (int) item_index );
365
366 return( volume_object );
367 }
368
369 /* The volumes iter() function
370 */
pyfsapfs_volumes_iter(pyfsapfs_volumes_t * sequence_object)371 PyObject *pyfsapfs_volumes_iter(
372 pyfsapfs_volumes_t *sequence_object )
373 {
374 static char *function = "pyfsapfs_volumes_iter";
375
376 if( sequence_object == NULL )
377 {
378 PyErr_Format(
379 PyExc_ValueError,
380 "%s: invalid sequence object.",
381 function );
382
383 return( NULL );
384 }
385 Py_IncRef(
386 (PyObject *) sequence_object );
387
388 return( (PyObject *) sequence_object );
389 }
390
391 /* The volumes iternext() function
392 */
pyfsapfs_volumes_iternext(pyfsapfs_volumes_t * sequence_object)393 PyObject *pyfsapfs_volumes_iternext(
394 pyfsapfs_volumes_t *sequence_object )
395 {
396 PyObject *volume_object = NULL;
397 static char *function = "pyfsapfs_volumes_iternext";
398
399 if( sequence_object == NULL )
400 {
401 PyErr_Format(
402 PyExc_ValueError,
403 "%s: invalid sequence object.",
404 function );
405
406 return( NULL );
407 }
408 if( sequence_object->get_item_by_index == NULL )
409 {
410 PyErr_Format(
411 PyExc_ValueError,
412 "%s: invalid sequence object - missing get item by index function.",
413 function );
414
415 return( NULL );
416 }
417 if( sequence_object->current_index < 0 )
418 {
419 PyErr_Format(
420 PyExc_ValueError,
421 "%s: invalid sequence object - invalid current index.",
422 function );
423
424 return( NULL );
425 }
426 if( sequence_object->number_of_items < 0 )
427 {
428 PyErr_Format(
429 PyExc_ValueError,
430 "%s: invalid sequence object - invalid number of items.",
431 function );
432
433 return( NULL );
434 }
435 if( sequence_object->current_index >= sequence_object->number_of_items )
436 {
437 PyErr_SetNone(
438 PyExc_StopIteration );
439
440 return( NULL );
441 }
442 volume_object = sequence_object->get_item_by_index(
443 sequence_object->parent_object,
444 sequence_object->current_index );
445
446 if( volume_object != NULL )
447 {
448 sequence_object->current_index++;
449 }
450 return( volume_object );
451 }
452
453