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