1 /*
2  * Python object wrapper of libfsntfs_file_entry_t
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 <narrow_string.h>
24 #include <types.h>
25 
26 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
27 #include <stdlib.h>
28 #endif
29 
30 #include "pyfsntfs_attribute.h"
31 #include "pyfsntfs_attributes.h"
32 #include "pyfsntfs_data_stream.h"
33 #include "pyfsntfs_data_streams.h"
34 #include "pyfsntfs_datetime.h"
35 #include "pyfsntfs_error.h"
36 #include "pyfsntfs_file_entries.h"
37 #include "pyfsntfs_file_entry.h"
38 #include "pyfsntfs_file_name_attribute.h"
39 #include "pyfsntfs_integer.h"
40 #include "pyfsntfs_libcerror.h"
41 #include "pyfsntfs_libfsntfs.h"
42 #include "pyfsntfs_object_identifier_attribute.h"
43 #include "pyfsntfs_python.h"
44 #include "pyfsntfs_reparse_point_attribute.h"
45 #include "pyfsntfs_security_descriptor_attribute.h"
46 #include "pyfsntfs_standard_information_attribute.h"
47 #include "pyfsntfs_unused.h"
48 #include "pyfsntfs_volume_information_attribute.h"
49 #include "pyfsntfs_volume_name_attribute.h"
50 
51 PyMethodDef pyfsntfs_file_entry_object_methods[] = {
52 
53 	/* Functions to access the file entry data */
54 
55 	{ "read_buffer",
56 	  (PyCFunction) pyfsntfs_file_entry_read_buffer,
57 	  METH_VARARGS | METH_KEYWORDS,
58 	  "read_buffer(size) -> String\n"
59 	  "\n"
60 	  "Reads a buffer of file entry data." },
61 
62 	{ "read_buffer_at_offset",
63 	  (PyCFunction) pyfsntfs_file_entry_read_buffer_at_offset,
64 	  METH_VARARGS | METH_KEYWORDS,
65 	  "read_buffer_at_offset(size, offset) -> String\n"
66 	  "\n"
67 	  "Reads a buffer of file entry data at a specific offset." },
68 
69 	{ "seek_offset",
70 	  (PyCFunction) pyfsntfs_file_entry_seek_offset,
71 	  METH_VARARGS | METH_KEYWORDS,
72 	  "seek_offset(offset, whence) -> None\n"
73 	  "\n"
74 	  "Seeks an offset within the file entry data." },
75 
76 	{ "get_offset",
77 	  (PyCFunction) pyfsntfs_file_entry_get_offset,
78 	  METH_NOARGS,
79 	  "get_offset() -> Integer\n"
80 	  "\n"
81 	  "Returns the current offset within the file entry data." },
82 
83 	/* Some Pythonesque aliases */
84 
85 	{ "read",
86 	  (PyCFunction) pyfsntfs_file_entry_read_buffer,
87 	  METH_VARARGS | METH_KEYWORDS,
88 	  "read(size) -> String\n"
89 	  "\n"
90 	  "Reads a buffer of file entry data." },
91 
92 	{ "seek",
93 	  (PyCFunction) pyfsntfs_file_entry_seek_offset,
94 	  METH_VARARGS | METH_KEYWORDS,
95 	  "seek(offset, whence) -> None\n"
96 	  "\n"
97 	  "Seeks an offset within the file entry data." },
98 
99 	{ "tell",
100 	  (PyCFunction) pyfsntfs_file_entry_get_offset,
101 	  METH_NOARGS,
102 	  "tell() -> Integer\n"
103 	  "\n"
104 	  "Returns the current offset within the file entry data." },
105 
106 	/* Functions to access the metadata */
107 
108 	{ "get_size",
109 	  (PyCFunction) pyfsntfs_file_entry_get_size,
110 	  METH_NOARGS,
111 	  "get_size() -> Integer\n"
112 	  "\n"
113 	  "Returns the size data." },
114 
115 	/* Functions to access the extents */
116 
117 	{ "get_number_of_extents",
118 	  (PyCFunction) pyfsntfs_file_entry_get_number_of_extents,
119 	  METH_NOARGS,
120 	  "get_number_of_extents() -> Integer\n"
121 	  "\n"
122 	  "Retrieves the number of extents." },
123 
124 	{ "get_extent",
125 	  (PyCFunction) pyfsntfs_file_entry_get_extent,
126 	  METH_VARARGS | METH_KEYWORDS,
127 	  "get_extent(extent_index) -> Tuple( Integer, Integer, Integer )\n"
128 	  "\n"
129 	  "Retrieves a specific extent.\t"
130           "The extent is a tuple of offset, size and flags." },
131 
132 	/* Functions to access the file entry data */
133 
134 	{ "is_empty",
135 	  (PyCFunction) pyfsntfs_file_entry_is_empty,
136 	  METH_NOARGS,
137 	  "is_empty() -> Boolean\n"
138 	  "\n"
139 	  "Determines if the file entry is empty." },
140 
141 	{ "is_allocated",
142 	  (PyCFunction) pyfsntfs_file_entry_is_allocated,
143 	  METH_NOARGS,
144 	  "is_allocated() -> Boolean\n"
145 	  "\n"
146 	  "Determines if the file entry is allocated." },
147 
148 	{ "has_directory_entries_index",
149 	  (PyCFunction) pyfsntfs_file_entry_has_directory_entries_index,
150 	  METH_NOARGS,
151 	  "has_directory_entries_index() -> Boolean\n"
152 	  "\n"
153 	  "Determines if the file entry has a directory entries index." },
154 
155 	{ "has_default_data_stream",
156 	  (PyCFunction) pyfsntfs_file_entry_has_default_data_stream,
157 	  METH_NOARGS,
158 	  "has_default_data_stream() -> Boolean\n"
159 	  "\n"
160 	  "Determines if the file entry has a default data stream." },
161 
162 	{ "get_file_reference",
163 	  (PyCFunction) pyfsntfs_file_entry_get_file_reference,
164 	  METH_NOARGS,
165 	  "get_file_reference() -> Integer\n"
166 	  "\n"
167 	  "Returns the file reference, a combination of MFT entry index and sequence number." },
168 
169 	{ "get_base_record_file_reference",
170 	  (PyCFunction) pyfsntfs_file_entry_get_base_record_file_reference,
171 	  METH_NOARGS,
172 	  "get_base_record_file_reference() -> Integer\n"
173 	  "\n"
174 	  "Returns the base record file reference, a combination of MFT entry index and sequence number." },
175 
176 	{ "get_parent_file_reference",
177 	  (PyCFunction) pyfsntfs_file_entry_get_parent_file_reference,
178 	  METH_NOARGS,
179 	  "get_parent_file_reference() -> Integer or None\n"
180 	  "\n"
181 	  "Returns the parent file reference, a combination of MFT entry index and sequence number." },
182 
183 	{ "get_parent_file_reference_by_attribute_index",
184 	  (PyCFunction) pyfsntfs_file_entry_get_parent_file_reference_by_attribute_index,
185 	  METH_VARARGS | METH_KEYWORDS,
186 	  "get_parent_file_reference_by_attribute_index(attribute_index) -> Integer\n"
187 	  "\n"
188 	  "Returns the parent file reference, a combination of MFT entry index and sequence number." },
189 
190 	{ "get_journal_sequence_number",
191 	  (PyCFunction) pyfsntfs_file_entry_get_journal_sequence_number,
192 	  METH_NOARGS,
193 	  "get_journal_sequence_number() -> Integer\n"
194 	  "\n"
195 	  "Returns the journal sequence number." },
196 
197 	{ "get_creation_time",
198 	  (PyCFunction) pyfsntfs_file_entry_get_creation_time,
199 	  METH_NOARGS,
200 	  "get_creation_time() -> Datetime or None\n"
201 	  "\n"
202 	  "Returns the creation date and time." },
203 
204 	{ "get_creation_time_as_integer",
205 	  (PyCFunction) pyfsntfs_file_entry_get_creation_time_as_integer,
206 	  METH_NOARGS,
207 	  "get_creation_time_as_integer() -> Integer or None\n"
208 	  "\n"
209 	  "Returns the creation date and time as a 64-bit integer containing a FILETIME value." },
210 
211 	{ "get_modification_time",
212 	  (PyCFunction) pyfsntfs_file_entry_get_modification_time,
213 	  METH_NOARGS,
214 	  "get_modification_time() -> Datetime or None\n"
215 	  "\n"
216 	  "Returns the modification date and time." },
217 
218 	{ "get_modification_time_as_integer",
219 	  (PyCFunction) pyfsntfs_file_entry_get_modification_time_as_integer,
220 	  METH_NOARGS,
221 	  "get_modification_time_as_integer() -> Integer or None\n"
222 	  "\n"
223 	  "Returns the modification date and time as a 64-bit integer containing a FILETIME value." },
224 
225 	{ "get_access_time",
226 	  (PyCFunction) pyfsntfs_file_entry_get_access_time,
227 	  METH_NOARGS,
228 	  "get_access_time() -> Datetime or None\n"
229 	  "\n"
230 	  "Returns the access date and time." },
231 
232 	{ "get_access_time_as_integer",
233 	  (PyCFunction) pyfsntfs_file_entry_get_access_time_as_integer,
234 	  METH_NOARGS,
235 	  "get_access_time_as_integer() -> Integer or None\n"
236 	  "\n"
237 	  "Returns the access date and time as a 64-bit integer containing a FILETIME value." },
238 
239 	{ "get_entry_modification_time",
240 	  (PyCFunction) pyfsntfs_file_entry_get_entry_modification_time,
241 	  METH_NOARGS,
242 	  "get_entry_modification_time() -> Datetime or None\n"
243 	  "\n"
244 	  "Returns the entry modification date and time." },
245 
246 	{ "get_entry_modification_time_as_integer",
247 	  (PyCFunction) pyfsntfs_file_entry_get_entry_modification_time_as_integer,
248 	  METH_NOARGS,
249 	  "get_entry_modification_time_as_integer() -> Integer or None\n"
250 	  "\n"
251 	  "Returns the entry modification date and time as a 64-bit integer containing a FILETIME value." },
252 
253 	{ "get_name",
254 	  (PyCFunction) pyfsntfs_file_entry_get_name,
255 	  METH_NOARGS,
256 	  "get_name() -> Unicode string or None\n"
257 	  "\n"
258 	  "Returns the name." },
259 
260 	{ "get_name_attribute_index",
261 	  (PyCFunction) pyfsntfs_file_entry_get_name_attribute_index,
262 	  METH_NOARGS,
263 	  "get_name_attribute_index() -> Integer or None\n"
264 	  "\n"
265 	  "Returns the attribute index corresponding to the name." },
266 
267 	{ "get_name_by_attribute_index",
268 	  (PyCFunction) pyfsntfs_file_entry_get_name_by_attribute_index,
269 	  METH_VARARGS | METH_KEYWORDS,
270 	  "get_name_by_attribute_index(attribute_index) -> Unicode string or None\n"
271 	  "\n"
272 	  "Returns the name." },
273 
274 	{ "get_file_attribute_flags",
275 	  (PyCFunction) pyfsntfs_file_entry_get_file_attribute_flags,
276 	  METH_NOARGS,
277 	  "get_file_attribute_flags() -> Integer or None\n"
278 	  "\n"
279 	  "Returns the file attribute flags." },
280 
281 	{ "get_path_hint",
282 	  (PyCFunction) pyfsntfs_file_entry_get_path_hint,
283 	  METH_VARARGS | METH_KEYWORDS,
284 	  "get_path_hint(attribute_index) -> Unicode string or None\n"
285 	  "\n"
286 	  "Returns the name." },
287 
288 	{ "get_symbolic_link_target",
289 	  (PyCFunction) pyfsntfs_file_entry_get_symbolic_link_target,
290 	  METH_NOARGS,
291 	  "get_symbolic_link_target() -> Unicode string or None\n"
292 	  "\n"
293 	  "Returns the symbolic link target." },
294 
295 	{ "get_security_descriptor_data",
296 	  (PyCFunction) pyfsntfs_file_entry_get_security_descriptor_data,
297 	  METH_NOARGS,
298 	  "get_security_descriptor_data() -> String or None\n"
299 	  "\n"
300 	  "Returns the security descriptor data." },
301 
302 	/* Functions to access the attributes */
303 
304 	{ "get_number_of_attributes",
305 	  (PyCFunction) pyfsntfs_file_entry_get_number_of_attributes,
306 	  METH_NOARGS,
307 	  "get_number_of_attributes() -> Integer\n"
308 	  "\n"
309 	  "Retrieves the number of attributes." },
310 
311 	{ "get_attribute",
312 	  (PyCFunction) pyfsntfs_file_entry_get_attribute,
313 	  METH_VARARGS | METH_KEYWORDS,
314 	  "get_attribute(attribute_index) -> Object\n"
315 	  "\n"
316 	  "Retrieves a specific attribute." },
317 
318 	/* Functions to access the alternate data streams */
319 
320 	{ "get_number_of_alternate_data_streams",
321 	  (PyCFunction) pyfsntfs_file_entry_get_number_of_alternate_data_streams,
322 	  METH_NOARGS,
323 	  "get_number_of_alternate_data_streams() -> Integer\n"
324 	  "\n"
325 	  "Retrieves the number of alternate data streams." },
326 
327 	{ "get_alternate_data_stream",
328 	  (PyCFunction) pyfsntfs_file_entry_get_alternate_data_stream,
329 	  METH_VARARGS | METH_KEYWORDS,
330 	  "get_alternate_data_stream(alternate_data_stream_index) -> Object\n"
331 	  "\n"
332 	  "Retrieves a specific alternate data stream." },
333 
334 	{ "has_alternate_data_stream_by_name",
335 	  (PyCFunction) pyfsntfs_file_entry_has_alternate_data_stream_by_name,
336 	  METH_VARARGS | METH_KEYWORDS,
337 	  "has_alternate_data_stream_by_name(name) -> Boolean\n"
338 	  "\n"
339 	  "Determines if there is an alternate data stream specified by the name." },
340 
341 	{ "get_alternate_data_stream_by_name",
342 	  (PyCFunction) pyfsntfs_file_entry_get_alternate_data_stream_by_name,
343 	  METH_VARARGS | METH_KEYWORDS,
344 	  "get_alternate_data_stream_by_name(name) -> Object or None\n"
345 	  "\n"
346 	  "Retrieves an alternate data stream specified by the name." },
347 
348 	/* Functions to access the sub file entries */
349 
350 	{ "get_number_of_sub_file_entries",
351 	  (PyCFunction) pyfsntfs_file_entry_get_number_of_sub_file_entries,
352 	  METH_NOARGS,
353 	  "get_number_of_sub_file_entries() -> Integer\n"
354 	  "\n"
355 	  "Retrieves the number of sub file entries." },
356 
357 	{ "get_sub_file_entry",
358 	  (PyCFunction) pyfsntfs_file_entry_get_sub_file_entry,
359 	  METH_VARARGS | METH_KEYWORDS,
360 	  "get_sub_file_entry(sub_file_entry_index) -> Object\n"
361 	  "\n"
362 	  "Retrieves a specific sub file entry." },
363 
364 	/* Sentinel */
365 	{ NULL, NULL, 0, NULL }
366 };
367 
368 PyGetSetDef pyfsntfs_file_entry_object_get_set_definitions[] = {
369 
370 	{ "size",
371 	  (getter) pyfsntfs_file_entry_get_size,
372 	  (setter) 0,
373 	  "The size of the data.",
374 	  NULL },
375 
376 	{ "number_of_extents",
377 	  (getter) pyfsntfs_file_entry_get_number_of_extents,
378 	  (setter) 0,
379 	  "The number of extents.",
380 	  NULL },
381 
382 	{ "file_reference",
383 	  (getter) pyfsntfs_file_entry_get_file_reference,
384 	  (setter) 0,
385 	  "The file reference, a combination of MFT entry index and sequence number.",
386 	  NULL },
387 
388 	{ "base_record_file_reference",
389 	  (getter) pyfsntfs_file_entry_get_base_record_file_reference,
390 	  (setter) 0,
391 	  "The base record file reference, a combination of MFT entry index and sequence number.",
392 	  NULL },
393 
394 	{ "parent_file_reference",
395 	  (getter) pyfsntfs_file_entry_get_parent_file_reference,
396 	  (setter) 0,
397 	  "The parent file reference, a combination of MFT entry index and sequence number.",
398 	  NULL },
399 
400 	{ "journal_sequence_number",
401 	  (getter) pyfsntfs_file_entry_get_journal_sequence_number,
402 	  (setter) 0,
403 	  "The journal sequence number.",
404 	  NULL },
405 
406 	{ "creation_time",
407 	  (getter) pyfsntfs_file_entry_get_creation_time,
408 	  (setter) 0,
409 	  "The creation date and time.",
410 	  NULL },
411 
412 	{ "modification_time",
413 	  (getter) pyfsntfs_file_entry_get_modification_time,
414 	  (setter) 0,
415 	  "The modification date and time.",
416 	  NULL },
417 
418 	{ "access_time",
419 	  (getter) pyfsntfs_file_entry_get_access_time,
420 	  (setter) 0,
421 	  "The access date and time.",
422 	  NULL },
423 
424 	{ "entry_modification_time",
425 	  (getter) pyfsntfs_file_entry_get_entry_modification_time,
426 	  (setter) 0,
427 	  "The entry modification date and time.",
428 	  NULL },
429 
430 	{ "name",
431 	  (getter) pyfsntfs_file_entry_get_name,
432 	  (setter) 0,
433 	  "The name.",
434 	  NULL },
435 
436 	{ "name_attribute_index",
437 	  (getter) pyfsntfs_file_entry_get_name_attribute_index,
438 	  (setter) 0,
439 	  "The name.",
440 	  NULL },
441 
442 	{ "file_attribute_flags",
443 	  (getter) pyfsntfs_file_entry_get_file_attribute_flags,
444 	  (setter) 0,
445 	  "The file attribute flags.",
446 	  NULL },
447 
448 	{ "symbolic_link_target",
449 	  (getter) pyfsntfs_file_entry_get_symbolic_link_target,
450 	  (setter) 0,
451 	  "The symbolic link target.",
452 	  NULL },
453 
454 	{ "security_descriptor_data",
455 	  (getter) pyfsntfs_file_entry_get_security_descriptor_data,
456 	  (setter) 0,
457 	  "The security descriptor data.",
458 	  NULL },
459 
460 	{ "number_of_attributes",
461 	  (getter) pyfsntfs_file_entry_get_number_of_attributes,
462 	  (setter) 0,
463 	  "The number of attributes.",
464 	  NULL },
465 
466 	{ "attributes",
467 	  (getter) pyfsntfs_file_entry_get_attributes,
468 	  (setter) 0,
469 	  "The attributes",
470 	  NULL },
471 
472 	{ "number_of_alternate_data_streams",
473 	  (getter) pyfsntfs_file_entry_get_number_of_alternate_data_streams,
474 	  (setter) 0,
475 	  "The number of alternate data streams.",
476 	  NULL },
477 
478 	{ "alternate_data_streams",
479 	  (getter) pyfsntfs_file_entry_get_alternate_data_streams,
480 	  (setter) 0,
481 	  "The alternate data streams",
482 	  NULL },
483 
484 	{ "number_of_sub_file_entries",
485 	  (getter) pyfsntfs_file_entry_get_number_of_sub_file_entries,
486 	  (setter) 0,
487 	  "The number of sub file entries.",
488 	  NULL },
489 
490 	{ "sub_file_entries",
491 	  (getter) pyfsntfs_file_entry_get_sub_file_entries,
492 	  (setter) 0,
493 	  "The sub file entries",
494 	  NULL },
495 
496 	/* Sentinel */
497 	{ NULL, NULL, NULL, NULL, NULL }
498 };
499 
500 PyTypeObject pyfsntfs_file_entry_type_object = {
501 	PyVarObject_HEAD_INIT( NULL, 0 )
502 
503 	/* tp_name */
504 	"pyfsntfs.file_entry",
505 	/* tp_basicsize */
506 	sizeof( pyfsntfs_file_entry_t ),
507 	/* tp_itemsize */
508 	0,
509 	/* tp_dealloc */
510 	(destructor) pyfsntfs_file_entry_free,
511 	/* tp_print */
512 	0,
513 	/* tp_getattr */
514 	0,
515 	/* tp_setattr */
516 	0,
517 	/* tp_compare */
518 	0,
519 	/* tp_repr */
520 	0,
521 	/* tp_as_number */
522 	0,
523 	/* tp_as_sequence */
524 	0,
525 	/* tp_as_mapping */
526 	0,
527 	/* tp_hash */
528 	0,
529 	/* tp_call */
530 	0,
531 	/* tp_str */
532 	0,
533 	/* tp_getattro */
534 	0,
535 	/* tp_setattro */
536 	0,
537 	/* tp_as_buffer */
538 	0,
539 	/* tp_flags */
540 	Py_TPFLAGS_DEFAULT,
541 	/* tp_doc */
542 	"pyfsntfs file entry object (wraps libfsntfs_file_entry_t)",
543 	/* tp_traverse */
544 	0,
545 	/* tp_clear */
546 	0,
547 	/* tp_richcompare */
548 	0,
549 	/* tp_weaklistoffset */
550 	0,
551 	/* tp_iter */
552 	0,
553 	/* tp_iternext */
554 	0,
555 	/* tp_methods */
556 	pyfsntfs_file_entry_object_methods,
557 	/* tp_members */
558 	0,
559 	/* tp_getset */
560 	pyfsntfs_file_entry_object_get_set_definitions,
561 	/* tp_base */
562 	0,
563 	/* tp_dict */
564 	0,
565 	/* tp_descr_get */
566 	0,
567 	/* tp_descr_set */
568 	0,
569 	/* tp_dictoffset */
570 	0,
571 	/* tp_init */
572 	(initproc) pyfsntfs_file_entry_init,
573 	/* tp_alloc */
574 	0,
575 	/* tp_new */
576 	0,
577 	/* tp_free */
578 	0,
579 	/* tp_is_gc */
580 	0,
581 	/* tp_bases */
582 	NULL,
583 	/* tp_mro */
584 	NULL,
585 	/* tp_cache */
586 	NULL,
587 	/* tp_subclasses */
588 	NULL,
589 	/* tp_weaklist */
590 	NULL,
591 	/* tp_del */
592 	0
593 };
594 
595 /* Creates a new file entry object
596  * Returns a Python object if successful or NULL on error
597  */
pyfsntfs_file_entry_new(libfsntfs_file_entry_t * file_entry,PyObject * parent_object)598 PyObject *pyfsntfs_file_entry_new(
599            libfsntfs_file_entry_t *file_entry,
600            PyObject *parent_object )
601 {
602 	pyfsntfs_file_entry_t *pyfsntfs_file_entry = NULL;
603 	static char *function                      = "pyfsntfs_file_entry_new";
604 
605 	if( file_entry == NULL )
606 	{
607 		PyErr_Format(
608 		 PyExc_ValueError,
609 		 "%s: invalid file entry.",
610 		 function );
611 
612 		return( NULL );
613 	}
614 	/* PyObject_New does not invoke tp_init
615 	 */
616 	pyfsntfs_file_entry = PyObject_New(
617 	                       struct pyfsntfs_file_entry,
618 	                       &pyfsntfs_file_entry_type_object );
619 
620 	if( pyfsntfs_file_entry == NULL )
621 	{
622 		PyErr_Format(
623 		 PyExc_MemoryError,
624 		 "%s: unable to initialize file entry.",
625 		 function );
626 
627 		goto on_error;
628 	}
629 	pyfsntfs_file_entry->file_entry    = file_entry;
630 	pyfsntfs_file_entry->parent_object = parent_object;
631 
632 	if( pyfsntfs_file_entry->parent_object != NULL )
633 	{
634 		Py_IncRef(
635 		 pyfsntfs_file_entry->parent_object );
636 	}
637 	return( (PyObject *) pyfsntfs_file_entry );
638 
639 on_error:
640 	if( pyfsntfs_file_entry != NULL )
641 	{
642 		Py_DecRef(
643 		 (PyObject *) pyfsntfs_file_entry );
644 	}
645 	return( NULL );
646 }
647 
648 /* Initializes a file entry object
649  * Returns 0 if successful or -1 on error
650  */
pyfsntfs_file_entry_init(pyfsntfs_file_entry_t * pyfsntfs_file_entry)651 int pyfsntfs_file_entry_init(
652      pyfsntfs_file_entry_t *pyfsntfs_file_entry )
653 {
654 	static char *function = "pyfsntfs_file_entry_init";
655 
656 	if( pyfsntfs_file_entry == NULL )
657 	{
658 		PyErr_Format(
659 		 PyExc_ValueError,
660 		 "%s: invalid file entry.",
661 		 function );
662 
663 		return( -1 );
664 	}
665 	/* Make sure libfsntfs file entry is set to NULL
666 	 */
667 	pyfsntfs_file_entry->file_entry = NULL;
668 
669 	PyErr_Format(
670 	 PyExc_NotImplementedError,
671 	 "%s: initialize of file entry not supported.",
672 	 function );
673 
674 	return( -1 );
675 }
676 
677 /* Frees a file entry object
678  */
pyfsntfs_file_entry_free(pyfsntfs_file_entry_t * pyfsntfs_file_entry)679 void pyfsntfs_file_entry_free(
680       pyfsntfs_file_entry_t *pyfsntfs_file_entry )
681 {
682 	struct _typeobject *ob_type = NULL;
683 	libcerror_error_t *error    = NULL;
684 	static char *function       = "pyfsntfs_file_entry_free";
685 	int result                  = 0;
686 
687 	if( pyfsntfs_file_entry == NULL )
688 	{
689 		PyErr_Format(
690 		 PyExc_ValueError,
691 		 "%s: invalid file entry.",
692 		 function );
693 
694 		return;
695 	}
696 	ob_type = Py_TYPE(
697 	           pyfsntfs_file_entry );
698 
699 	if( ob_type == NULL )
700 	{
701 		PyErr_Format(
702 		 PyExc_ValueError,
703 		 "%s: missing ob_type.",
704 		 function );
705 
706 		return;
707 	}
708 	if( ob_type->tp_free == NULL )
709 	{
710 		PyErr_Format(
711 		 PyExc_ValueError,
712 		 "%s: invalid ob_type - missing tp_free.",
713 		 function );
714 
715 		return;
716 	}
717 	if( pyfsntfs_file_entry->file_entry != NULL )
718 	{
719 		Py_BEGIN_ALLOW_THREADS
720 
721 		result = libfsntfs_file_entry_free(
722 		          &( pyfsntfs_file_entry->file_entry ),
723 		          &error );
724 
725 		Py_END_ALLOW_THREADS
726 
727 		if( result != 1 )
728 		{
729 			pyfsntfs_error_raise(
730 			 error,
731 			 PyExc_MemoryError,
732 			 "%s: unable to free libfsntfs file entry.",
733 			 function );
734 
735 			libcerror_error_free(
736 			 &error );
737 		}
738 	}
739 	if( pyfsntfs_file_entry->parent_object != NULL )
740 	{
741 		Py_DecRef(
742 		 pyfsntfs_file_entry->parent_object );
743 	}
744 	ob_type->tp_free(
745 	 (PyObject*) pyfsntfs_file_entry );
746 }
747 
748 /* Reads a buffer of data from the file entry
749  * Returns a Python object holding the data if successful or NULL on error
750  */
pyfsntfs_file_entry_read_buffer(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)751 PyObject *pyfsntfs_file_entry_read_buffer(
752            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
753            PyObject *arguments,
754            PyObject *keywords )
755 {
756 	libcerror_error_t *error    = NULL;
757 	PyObject *integer_object    = NULL;
758 	PyObject *string_object     = NULL;
759 	static char *function       = "pyfsntfs_file_entry_read_buffer";
760 	static char *keyword_list[] = { "size", NULL };
761 	char *buffer                = NULL;
762 	size64_t read_size          = 0;
763 	ssize_t read_count          = 0;
764 	int result                  = 0;
765 
766 	if( pyfsntfs_file_entry == NULL )
767 	{
768 		PyErr_Format(
769 		 PyExc_ValueError,
770 		 "%s: invalid pyfsntfs file entry.",
771 		 function );
772 
773 		return( NULL );
774 	}
775 	if( pyfsntfs_file_entry->file_entry == NULL )
776 	{
777 		PyErr_Format(
778 		 PyExc_ValueError,
779 		 "%s: invalid pyfsntfs file entry - missing libfsntfs file entry.",
780 		 function );
781 
782 		return( NULL );
783 	}
784 	if( PyArg_ParseTupleAndKeywords(
785 	     arguments,
786 	     keywords,
787 	     "|O",
788 	     keyword_list,
789 	     &integer_object ) == 0 )
790 	{
791 		return( NULL );
792 	}
793 	PyErr_Clear();
794 
795 	Py_BEGIN_ALLOW_THREADS
796 
797 	result = libfsntfs_file_entry_has_default_data_stream(
798 	          pyfsntfs_file_entry->file_entry,
799 	          &error );
800 
801 	Py_END_ALLOW_THREADS
802 
803 	if( result == -1 )
804 	{
805 		pyfsntfs_error_raise(
806 		 error,
807 		 PyExc_IOError,
808 		 "%s: unable to determine if file entry has default data stream.",
809 		 function );
810 
811 		libcerror_error_free(
812 		 &error );
813 
814 		return( NULL );
815 	}
816 	else if( result == 0 )
817 	{
818 		PyErr_Format(
819 		 PyExc_IOError,
820 		 "%s: missing default data stream.",
821 		 function );
822 
823 		return( NULL );
824 	}
825 	if( integer_object == NULL )
826 	{
827 		result = 0;
828 	}
829 	else
830 	{
831 		result = PyObject_IsInstance(
832 		          integer_object,
833 		          (PyObject *) &PyLong_Type );
834 
835 		if( result == -1 )
836 		{
837 			pyfsntfs_error_fetch_and_raise(
838 			 PyExc_RuntimeError,
839 			 "%s: unable to determine if integer object is of type long.",
840 			 function );
841 
842 			return( NULL );
843 		}
844 #if PY_MAJOR_VERSION < 3
845 		else if( result == 0 )
846 		{
847 			PyErr_Clear();
848 
849 			result = PyObject_IsInstance(
850 				  integer_object,
851 				  (PyObject *) &PyInt_Type );
852 
853 			if( result == -1 )
854 			{
855 				pyfsntfs_error_fetch_and_raise(
856 				 PyExc_RuntimeError,
857 				 "%s: unable to determine if integer object is of type int.",
858 				 function );
859 
860 				return( NULL );
861 			}
862 		}
863 #endif
864 	}
865 	if( result != 0 )
866 	{
867 		if( pyfsntfs_integer_unsigned_copy_to_64bit(
868 		     integer_object,
869 		     (uint64_t *) &read_size,
870 		     &error ) != 1 )
871 		{
872 			pyfsntfs_error_raise(
873 			 error,
874 			 PyExc_IOError,
875 			 "%s: unable to convert integer object into read size.",
876 			 function );
877 
878 			libcerror_error_free(
879 			 &error );
880 
881 			return( NULL );
882 		}
883 	}
884 	else if( ( integer_object == NULL )
885 	      || ( integer_object == Py_None ) )
886 	{
887 		Py_BEGIN_ALLOW_THREADS
888 
889 		result = libfsntfs_file_entry_get_size(
890 			  pyfsntfs_file_entry->file_entry,
891 			  &read_size,
892 			  &error );
893 
894 		Py_END_ALLOW_THREADS
895 
896 		if( result != 1 )
897 		{
898 			pyfsntfs_error_raise(
899 			 error,
900 			 PyExc_IOError,
901 			 "%s: unable to retrieve size.",
902 			 function );
903 
904 			libcerror_error_free(
905 			 &error );
906 
907 			return( NULL );
908 		}
909 	}
910 	else
911 	{
912 		PyErr_Format(
913 		 PyExc_TypeError,
914 		 "%s: unsupported integer object type.",
915 		 function );
916 
917 		return( NULL );
918 	}
919 	if( read_size == 0 )
920 	{
921 #if PY_MAJOR_VERSION >= 3
922 		string_object = PyBytes_FromString(
923 		                 "" );
924 #else
925 		string_object = PyString_FromString(
926 		                 "" );
927 #endif
928 		return( string_object );
929 	}
930 	/* Make sure the data fits into a memory buffer
931 	 */
932 	if( ( read_size > (size64_t) INT_MAX )
933 	 || ( read_size > (size64_t) SSIZE_MAX ) )
934 	{
935 		PyErr_Format(
936 		 PyExc_ValueError,
937 		 "%s: invalid argument read size value exceeds maximum.",
938 		 function );
939 
940 		return( NULL );
941 	}
942 #if PY_MAJOR_VERSION >= 3
943 	string_object = PyBytes_FromStringAndSize(
944 	                 NULL,
945 	                 read_size );
946 
947 	buffer = PyBytes_AsString(
948 	          string_object );
949 #else
950 	/* Note that a size of 0 is not supported
951 	 */
952 	string_object = PyString_FromStringAndSize(
953 	                 NULL,
954 	                 read_size );
955 
956 	buffer = PyString_AsString(
957 	          string_object );
958 #endif
959 	Py_BEGIN_ALLOW_THREADS
960 
961 	read_count = libfsntfs_file_entry_read_buffer(
962 	              pyfsntfs_file_entry->file_entry,
963 	              (uint8_t *) buffer,
964 	              (size_t) read_size,
965 	              &error );
966 
967 	Py_END_ALLOW_THREADS
968 
969 	if( read_count <= -1 )
970 	{
971 		pyfsntfs_error_raise(
972 		 error,
973 		 PyExc_IOError,
974 		 "%s: unable to read data.",
975 		 function );
976 
977 		libcerror_error_free(
978 		 &error );
979 
980 		Py_DecRef(
981 		 (PyObject *) string_object );
982 
983 		return( NULL );
984 	}
985 	/* Need to resize the string here in case read_size was not fully read.
986 	 */
987 #if PY_MAJOR_VERSION >= 3
988 	if( _PyBytes_Resize(
989 	     &string_object,
990 	     (Py_ssize_t) read_count ) != 0 )
991 #else
992 	if( _PyString_Resize(
993 	     &string_object,
994 	     (Py_ssize_t) read_count ) != 0 )
995 #endif
996 	{
997 		Py_DecRef(
998 		 (PyObject *) string_object );
999 
1000 		return( NULL );
1001 	}
1002 	return( string_object );
1003 }
1004 
1005 /* Reads a buffer of data at a specific foffset from the file entry
1006  * Returns a Python object holding the data if successful or NULL on error
1007  */
pyfsntfs_file_entry_read_buffer_at_offset(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)1008 PyObject *pyfsntfs_file_entry_read_buffer_at_offset(
1009            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1010            PyObject *arguments,
1011            PyObject *keywords )
1012 {
1013 	libcerror_error_t *error    = NULL;
1014 	PyObject *integer_object    = NULL;
1015 	PyObject *string_object     = NULL;
1016 	static char *function       = "pyfsntfs_file_entry_read_buffer_at_offset";
1017 	static char *keyword_list[] = { "size", "offset", NULL };
1018 	char *buffer                = NULL;
1019 	off64_t read_offset         = 0;
1020 	size64_t read_size          = 0;
1021 	ssize_t read_count          = 0;
1022 	int result                  = 0;
1023 
1024 	if( pyfsntfs_file_entry == NULL )
1025 	{
1026 		PyErr_Format(
1027 		 PyExc_ValueError,
1028 		 "%s: invalid pyfsntfs file entry.",
1029 		 function );
1030 
1031 		return( NULL );
1032 	}
1033 	if( pyfsntfs_file_entry->file_entry == NULL )
1034 	{
1035 		PyErr_Format(
1036 		 PyExc_ValueError,
1037 		 "%s: invalid pyfsntfs file entry - missing libfsntfs file entry.",
1038 		 function );
1039 
1040 		return( NULL );
1041 	}
1042 	if( PyArg_ParseTupleAndKeywords(
1043 	     arguments,
1044 	     keywords,
1045 	     "OL",
1046 	     keyword_list,
1047 	     &integer_object,
1048 	     &read_offset ) == 0 )
1049 	{
1050 		return( NULL );
1051 	}
1052 	Py_BEGIN_ALLOW_THREADS
1053 
1054 	result = libfsntfs_file_entry_has_default_data_stream(
1055 	          pyfsntfs_file_entry->file_entry,
1056 	          &error );
1057 
1058 	Py_END_ALLOW_THREADS
1059 
1060 	if( result == -1 )
1061 	{
1062 		pyfsntfs_error_raise(
1063 		 error,
1064 		 PyExc_IOError,
1065 		 "%s: unable to determine if file entry has default data stream.",
1066 		 function );
1067 
1068 		libcerror_error_free(
1069 		 &error );
1070 
1071 		return( NULL );
1072 	}
1073 	else if( result == 0 )
1074 	{
1075 		PyErr_Format(
1076 		 PyExc_IOError,
1077 		 "%s: missing default data stream.",
1078 		 function );
1079 
1080 		return( NULL );
1081 	}
1082 	result = PyObject_IsInstance(
1083 	          integer_object,
1084 	          (PyObject *) &PyLong_Type );
1085 
1086 	if( result == -1 )
1087 	{
1088 		pyfsntfs_error_fetch_and_raise(
1089 	         PyExc_RuntimeError,
1090 		 "%s: unable to determine if integer object is of type long.",
1091 		 function );
1092 
1093 		return( NULL );
1094 	}
1095 #if PY_MAJOR_VERSION < 3
1096 	else if( result == 0 )
1097 	{
1098 		PyErr_Clear();
1099 
1100 		result = PyObject_IsInstance(
1101 		          integer_object,
1102 		          (PyObject *) &PyInt_Type );
1103 
1104 		if( result == -1 )
1105 		{
1106 			pyfsntfs_error_fetch_and_raise(
1107 		         PyExc_RuntimeError,
1108 			 "%s: unable to determine if integer object is of type int.",
1109 			 function );
1110 
1111 			return( NULL );
1112 		}
1113 	}
1114 #endif
1115 	if( result != 0 )
1116 	{
1117 		if( pyfsntfs_integer_unsigned_copy_to_64bit(
1118 		     integer_object,
1119 		     (uint64_t *) &read_size,
1120 		     &error ) != 1 )
1121 		{
1122 			pyfsntfs_error_raise(
1123 			 error,
1124 			 PyExc_IOError,
1125 			 "%s: unable to convert integer object into read size.",
1126 			 function );
1127 
1128 			libcerror_error_free(
1129 			 &error );
1130 
1131 			return( NULL );
1132 		}
1133 	}
1134 	else if( integer_object == Py_None )
1135 	{
1136 		Py_BEGIN_ALLOW_THREADS
1137 
1138 		result = libfsntfs_file_entry_get_size(
1139 			  pyfsntfs_file_entry->file_entry,
1140 			  &read_size,
1141 			  &error );
1142 
1143 		Py_END_ALLOW_THREADS
1144 
1145 		if( result != 1 )
1146 		{
1147 			pyfsntfs_error_raise(
1148 			 error,
1149 			 PyExc_IOError,
1150 			 "%s: unable to retrieve size.",
1151 			 function );
1152 
1153 			libcerror_error_free(
1154 			 &error );
1155 
1156 			return( NULL );
1157 		}
1158 	}
1159 	else
1160 	{
1161 		PyErr_Format(
1162 		 PyExc_TypeError,
1163 		 "%s: unsupported integer object type.",
1164 		 function );
1165 
1166 		return( NULL );
1167 	}
1168 	if( read_size == 0 )
1169 	{
1170 #if PY_MAJOR_VERSION >= 3
1171 		string_object = PyBytes_FromString(
1172 		                 "" );
1173 #else
1174 		string_object = PyString_FromString(
1175 		                 "" );
1176 #endif
1177 		return( string_object );
1178 	}
1179 	/* Make sure the data fits into a memory buffer
1180 	 */
1181 	if( ( read_size > (size64_t) INT_MAX )
1182 	 || ( read_size > (size64_t) SSIZE_MAX ) )
1183 	{
1184 		PyErr_Format(
1185 		 PyExc_ValueError,
1186 		 "%s: invalid argument read size value exceeds maximum.",
1187 		 function );
1188 
1189 		return( NULL );
1190 	}
1191 #if PY_MAJOR_VERSION >= 3
1192 	string_object = PyBytes_FromStringAndSize(
1193 	                 NULL,
1194 	                 read_size );
1195 
1196 	buffer = PyBytes_AsString(
1197 	          string_object );
1198 #else
1199 	/* Note that a size of 0 is not supported
1200 	 */
1201 	string_object = PyString_FromStringAndSize(
1202 	                 NULL,
1203 	                 read_size );
1204 
1205 	buffer = PyString_AsString(
1206 	          string_object );
1207 #endif
1208 	Py_BEGIN_ALLOW_THREADS
1209 
1210 	read_count = libfsntfs_file_entry_read_buffer_at_offset(
1211 	              pyfsntfs_file_entry->file_entry,
1212 	              (uint8_t *) buffer,
1213 	              (size_t) read_size,
1214 	              (off64_t) read_offset,
1215 	              &error );
1216 
1217 	Py_END_ALLOW_THREADS
1218 
1219 	if( read_count <= -1 )
1220 	{
1221 		pyfsntfs_error_raise(
1222 		 error,
1223 		 PyExc_IOError,
1224 		 "%s: unable to read data.",
1225 		 function );
1226 
1227 		libcerror_error_free(
1228 		 &error );
1229 
1230 		Py_DecRef(
1231 		 (PyObject *) string_object );
1232 
1233 		return( NULL );
1234 	}
1235 	/* Need to resize the string here in case read_size was not fully read.
1236 	 */
1237 #if PY_MAJOR_VERSION >= 3
1238 	if( _PyBytes_Resize(
1239 	     &string_object,
1240 	     (Py_ssize_t) read_count ) != 0 )
1241 #else
1242 	if( _PyString_Resize(
1243 	     &string_object,
1244 	     (Py_ssize_t) read_count ) != 0 )
1245 #endif
1246 	{
1247 		Py_DecRef(
1248 		 (PyObject *) string_object );
1249 
1250 		return( NULL );
1251 	}
1252 	return( string_object );
1253 }
1254 
1255 /* Seeks a certain offset in the file entry data
1256  * Returns a Python object holding the offset if successful or NULL on error
1257  */
pyfsntfs_file_entry_seek_offset(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)1258 PyObject *pyfsntfs_file_entry_seek_offset(
1259            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1260            PyObject *arguments,
1261            PyObject *keywords )
1262 {
1263 	libcerror_error_t *error    = NULL;
1264 	static char *function       = "pyfsntfs_file_entry_seek_offset";
1265 	static char *keyword_list[] = { "offset", "whence", NULL };
1266 	off64_t offset              = 0;
1267 	int result                  = 0;
1268 	int whence                  = 0;
1269 
1270 	if( pyfsntfs_file_entry == NULL )
1271 	{
1272 		PyErr_Format(
1273 		 PyExc_ValueError,
1274 		 "%s: invalid pyfsntfs file entry.",
1275 		 function );
1276 
1277 		return( NULL );
1278 	}
1279 	if( pyfsntfs_file_entry->file_entry == NULL )
1280 	{
1281 		PyErr_Format(
1282 		 PyExc_ValueError,
1283 		 "%s: invalid pyfsntfs file entry - missing libfsntfs file entry.",
1284 		 function );
1285 
1286 		return( NULL );
1287 	}
1288 	if( PyArg_ParseTupleAndKeywords(
1289 	     arguments,
1290 	     keywords,
1291 	     "L|i",
1292 	     keyword_list,
1293 	     &offset,
1294 	     &whence ) == 0 )
1295 	{
1296 		return( NULL );
1297 	}
1298 	Py_BEGIN_ALLOW_THREADS
1299 
1300 	result = libfsntfs_file_entry_has_default_data_stream(
1301 	          pyfsntfs_file_entry->file_entry,
1302 	          &error );
1303 
1304 	Py_END_ALLOW_THREADS
1305 
1306 	if( result == -1 )
1307 	{
1308 		pyfsntfs_error_raise(
1309 		 error,
1310 		 PyExc_IOError,
1311 		 "%s: unable to determine if file entry has default data stream.",
1312 		 function );
1313 
1314 		libcerror_error_free(
1315 		 &error );
1316 
1317 		return( NULL );
1318 	}
1319 	else if( result == 0 )
1320 	{
1321 		PyErr_Format(
1322 		 PyExc_IOError,
1323 		 "%s: missing default data stream.",
1324 		 function );
1325 
1326 		return( NULL );
1327 	}
1328 	Py_BEGIN_ALLOW_THREADS
1329 
1330 	offset = libfsntfs_file_entry_seek_offset(
1331 	          pyfsntfs_file_entry->file_entry,
1332 	          offset,
1333 	          whence,
1334 	          &error );
1335 
1336 	Py_END_ALLOW_THREADS
1337 
1338 	if( offset == -1 )
1339 	{
1340 		pyfsntfs_error_raise(
1341 		 error,
1342 		 PyExc_IOError,
1343 		 "%s: unable to seek offset.",
1344 		 function );
1345 
1346 		libcerror_error_free(
1347 		 &error );
1348 
1349 		return( NULL );
1350 	}
1351 	Py_IncRef(
1352 	 Py_None );
1353 
1354 	return( Py_None );
1355 }
1356 
1357 /* Retrieves the offset
1358  * Returns a Python object if successful or NULL on error
1359  */
pyfsntfs_file_entry_get_offset(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)1360 PyObject *pyfsntfs_file_entry_get_offset(
1361            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1362            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
1363 {
1364 	libcerror_error_t *error = NULL;
1365 	PyObject *integer_object = NULL;
1366 	static char *function    = "pyfsntfs_file_entry_get_offset";
1367 	off64_t offset           = 0;
1368 	int result               = 0;
1369 
1370 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
1371 
1372 	if( pyfsntfs_file_entry == NULL )
1373 	{
1374 		PyErr_Format(
1375 		 PyExc_ValueError,
1376 		 "%s: invalid file entry.",
1377 		 function );
1378 
1379 		return( NULL );
1380 	}
1381 	Py_BEGIN_ALLOW_THREADS
1382 
1383 	result = libfsntfs_file_entry_has_default_data_stream(
1384 	          pyfsntfs_file_entry->file_entry,
1385 	          &error );
1386 
1387 	Py_END_ALLOW_THREADS
1388 
1389 	if( result == -1 )
1390 	{
1391 		pyfsntfs_error_raise(
1392 		 error,
1393 		 PyExc_IOError,
1394 		 "%s: unable to determine if file entry has default data stream.",
1395 		 function );
1396 
1397 		libcerror_error_free(
1398 		 &error );
1399 
1400 		return( NULL );
1401 	}
1402 	else if( result == 0 )
1403 	{
1404 		PyErr_Format(
1405 		 PyExc_IOError,
1406 		 "%s: missing default data stream.",
1407 		 function );
1408 
1409 		return( NULL );
1410 	}
1411 	Py_BEGIN_ALLOW_THREADS
1412 
1413 	result = libfsntfs_file_entry_get_offset(
1414 	          pyfsntfs_file_entry->file_entry,
1415 	          &offset,
1416 	          &error );
1417 
1418 	Py_END_ALLOW_THREADS
1419 
1420 	if( result != 1 )
1421 	{
1422 		pyfsntfs_error_raise(
1423 		 error,
1424 		 PyExc_IOError,
1425 		 "%s: unable to retrieve offset.",
1426 		 function );
1427 
1428 		libcerror_error_free(
1429 		 &error );
1430 
1431 		return( NULL );
1432 	}
1433 	integer_object = pyfsntfs_integer_signed_new_from_64bit(
1434 	                  (int64_t) offset );
1435 
1436 	return( integer_object );
1437 }
1438 
1439 /* Retrieves the size
1440  * Returns a Python object if successful or NULL on error
1441  */
pyfsntfs_file_entry_get_size(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)1442 PyObject *pyfsntfs_file_entry_get_size(
1443            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1444            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
1445 {
1446 	libcerror_error_t *error = NULL;
1447 	PyObject *integer_object = NULL;
1448 	static char *function    = "pyfsntfs_file_entry_get_size";
1449 	size64_t size            = 0;
1450 	int result               = 0;
1451 
1452 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
1453 
1454 	if( pyfsntfs_file_entry == NULL )
1455 	{
1456 		PyErr_Format(
1457 		 PyExc_ValueError,
1458 		 "%s: invalid file entry.",
1459 		 function );
1460 
1461 		return( NULL );
1462 	}
1463 	Py_BEGIN_ALLOW_THREADS
1464 
1465 	result = libfsntfs_file_entry_get_size(
1466 	          pyfsntfs_file_entry->file_entry,
1467 	          &size,
1468 	          &error );
1469 
1470 	Py_END_ALLOW_THREADS
1471 
1472 	if( result != 1 )
1473 	{
1474 		pyfsntfs_error_raise(
1475 		 error,
1476 		 PyExc_IOError,
1477 		 "%s: unable to retrieve size.",
1478 		 function );
1479 
1480 		libcerror_error_free(
1481 		 &error );
1482 
1483 		return( NULL );
1484 	}
1485 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
1486 	                  (uint64_t) size );
1487 
1488 	return( integer_object );
1489 }
1490 
1491 /* Retrieves the number of extents
1492  * Returns a Python object if successful or NULL on error
1493  */
pyfsntfs_file_entry_get_number_of_extents(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)1494 PyObject *pyfsntfs_file_entry_get_number_of_extents(
1495            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1496            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
1497 {
1498 	libcerror_error_t *error = NULL;
1499 	PyObject *integer_object = NULL;
1500 	static char *function    = "pyfsntfs_file_entry_get_number_of_extents";
1501 	int number_of_extents    = 0;
1502 	int result               = 0;
1503 
1504 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
1505 
1506 	if( pyfsntfs_file_entry == NULL )
1507 	{
1508 		PyErr_Format(
1509 		 PyExc_ValueError,
1510 		 "%s: invalid file entry.",
1511 		 function );
1512 
1513 		return( NULL );
1514 	}
1515 	Py_BEGIN_ALLOW_THREADS
1516 
1517 	result = libfsntfs_file_entry_get_number_of_extents(
1518 	          pyfsntfs_file_entry->file_entry,
1519 	          &number_of_extents,
1520 	          &error );
1521 
1522 	Py_END_ALLOW_THREADS
1523 
1524 	if( result != 1 )
1525 	{
1526 		pyfsntfs_error_raise(
1527 		 error,
1528 		 PyExc_IOError,
1529 		 "%s: unable to retrieve number of extents.",
1530 		 function );
1531 
1532 		libcerror_error_free(
1533 		 &error );
1534 
1535 		return( NULL );
1536 	}
1537 #if PY_MAJOR_VERSION >= 3
1538 	integer_object = PyLong_FromLong(
1539 	                  (long) number_of_extents );
1540 #else
1541 	integer_object = PyInt_FromLong(
1542 	                  (long) number_of_extents );
1543 #endif
1544 	return( integer_object );
1545 }
1546 
1547 /* Retrieves a specific extent by index
1548  * Returns a Python object if successful or NULL on error
1549  */
pyfsntfs_file_entry_get_extent_by_index(pyfsntfs_file_entry_t * pyfsntfs_file_entry,int extent_index)1550 PyObject *pyfsntfs_file_entry_get_extent_by_index(
1551            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1552            int extent_index )
1553 {
1554 	libcerror_error_t *error = NULL;
1555 	PyObject *integer_object = NULL;
1556 	PyObject *tuple_object   = NULL;
1557 	static char *function    = "pyfsntfs_file_entry_get_extent_by_index";
1558 	off64_t extent_offset    = 0;
1559 	size64_t extent_size     = 0;
1560 	uint32_t extent_flags    = 0;
1561 	int result               = 0;
1562 
1563 	if( pyfsntfs_file_entry == NULL )
1564 	{
1565 		PyErr_Format(
1566 		 PyExc_ValueError,
1567 		 "%s: invalid file entry.",
1568 		 function );
1569 
1570 		return( NULL );
1571 	}
1572 	Py_BEGIN_ALLOW_THREADS
1573 
1574 	result = libfsntfs_file_entry_get_extent_by_index(
1575 	          pyfsntfs_file_entry->file_entry,
1576 	          extent_index,
1577 	          &extent_offset,
1578 	          &extent_size,
1579 	          &extent_flags,
1580 	          &error );
1581 
1582 	Py_END_ALLOW_THREADS
1583 
1584 	if( result != 1 )
1585 	{
1586 		pyfsntfs_error_raise(
1587 		 error,
1588 		 PyExc_IOError,
1589 		 "%s: unable to retrieve extent: %d.",
1590 		 function,
1591 		 extent_index );
1592 
1593 		libcerror_error_free(
1594 		 &error );
1595 
1596 		goto on_error;
1597 	}
1598 	tuple_object = PyTuple_New(
1599                         3 );
1600 
1601 	integer_object = pyfsntfs_integer_signed_new_from_64bit(
1602 	                  (int64_t) extent_offset );
1603 
1604 	/* Tuple set item does not increment the reference count of the integer object
1605 	 */
1606 	if( PyTuple_SetItem(
1607 	     tuple_object,
1608 	     0,
1609 	     integer_object ) != 0 )
1610 	{
1611 		goto on_error;
1612 	}
1613 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
1614 	                  (uint64_t) extent_size );
1615 
1616 	/* Tuple set item does not increment the reference count of the integer object
1617 	 */
1618 	if( PyTuple_SetItem(
1619 	     tuple_object,
1620 	     1,
1621 	     integer_object ) != 0 )
1622 	{
1623 		goto on_error;
1624 	}
1625 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
1626 	                  (uint64_t) extent_flags );
1627 
1628 	/* Tuple set item does not increment the reference count of the integer object
1629 	 */
1630 	if( PyTuple_SetItem(
1631 	     tuple_object,
1632 	     2,
1633 	     integer_object ) != 0 )
1634 	{
1635 		goto on_error;
1636 	}
1637 	return( tuple_object );
1638 
1639 on_error:
1640 	if( integer_object != NULL )
1641 	{
1642 		Py_DecRef(
1643 		 (PyObject *) integer_object );
1644 	}
1645 	if( tuple_object != NULL )
1646 	{
1647 		Py_DecRef(
1648 		 (PyObject *) tuple_object );
1649 	}
1650 	return( NULL );
1651 }
1652 
1653 /* Retrieves a specific extent
1654  * Returns a Python object if successful or NULL on error
1655  */
pyfsntfs_file_entry_get_extent(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)1656 PyObject *pyfsntfs_file_entry_get_extent(
1657            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1658            PyObject *arguments,
1659            PyObject *keywords )
1660 {
1661 	PyObject *sequence_object   = NULL;
1662 	static char *keyword_list[] = { "extent_index", NULL };
1663 	int extent_index            = 0;
1664 
1665 	if( PyArg_ParseTupleAndKeywords(
1666 	     arguments,
1667 	     keywords,
1668 	     "i",
1669 	     keyword_list,
1670 	     &extent_index ) == 0 )
1671 	{
1672 		return( NULL );
1673 	}
1674 	sequence_object = pyfsntfs_file_entry_get_extent_by_index(
1675 	                   pyfsntfs_file_entry,
1676 	                   extent_index );
1677 
1678 	return( sequence_object );
1679 }
1680 
1681 /* Determines if the file entry is empty
1682  * Returns a Python object if successful or NULL on error
1683  */
pyfsntfs_file_entry_is_empty(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)1684 PyObject *pyfsntfs_file_entry_is_empty(
1685            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1686            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
1687 {
1688 	libcerror_error_t *error = NULL;
1689 	static char *function    = "pyfsntfs_file_entry_is_empty";
1690 	int result               = 0;
1691 
1692 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
1693 
1694 	if( pyfsntfs_file_entry == NULL )
1695 	{
1696 		PyErr_Format(
1697 		 PyExc_ValueError,
1698 		 "%s: invalid file entry.",
1699 		 function );
1700 
1701 		return( NULL );
1702 	}
1703 	Py_BEGIN_ALLOW_THREADS
1704 
1705 	result = libfsntfs_file_entry_is_empty(
1706 	          pyfsntfs_file_entry->file_entry,
1707 	          &error );
1708 
1709 	Py_END_ALLOW_THREADS
1710 
1711 	if( result == -1 )
1712 	{
1713 		pyfsntfs_error_raise(
1714 		 error,
1715 		 PyExc_IOError,
1716 		 "%s: unable to determine if file entry is empty.",
1717 		 function );
1718 
1719 		libcerror_error_free(
1720 		 &error );
1721 
1722 		return( NULL );
1723 	}
1724 	if( result != 0 )
1725 	{
1726 		Py_IncRef(
1727 		 (PyObject *) Py_True );
1728 
1729 		return( Py_True );
1730 	}
1731 	Py_IncRef(
1732 	 (PyObject *) Py_False );
1733 
1734 	return( Py_False );
1735 }
1736 
1737 /* Determines if the file entry is allocated (in use)
1738  * Returns a Python object if successful or NULL on error
1739  */
pyfsntfs_file_entry_is_allocated(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)1740 PyObject *pyfsntfs_file_entry_is_allocated(
1741            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1742            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
1743 {
1744 	libcerror_error_t *error = NULL;
1745 	static char *function    = "pyfsntfs_file_entry_is_allocated";
1746 	int result               = 0;
1747 
1748 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
1749 
1750 	if( pyfsntfs_file_entry == NULL )
1751 	{
1752 		PyErr_Format(
1753 		 PyExc_ValueError,
1754 		 "%s: invalid file entry.",
1755 		 function );
1756 
1757 		return( NULL );
1758 	}
1759 	Py_BEGIN_ALLOW_THREADS
1760 
1761 	result = libfsntfs_file_entry_is_allocated(
1762 	          pyfsntfs_file_entry->file_entry,
1763 	          &error );
1764 
1765 	Py_END_ALLOW_THREADS
1766 
1767 	if( result == -1 )
1768 	{
1769 		pyfsntfs_error_raise(
1770 		 error,
1771 		 PyExc_IOError,
1772 		 "%s: unable to determine if file entry is allocated.",
1773 		 function );
1774 
1775 		libcerror_error_free(
1776 		 &error );
1777 
1778 		return( NULL );
1779 	}
1780 	if( result != 0 )
1781 	{
1782 		Py_IncRef(
1783 		 (PyObject *) Py_True );
1784 
1785 		return( Py_True );
1786 	}
1787 	Py_IncRef(
1788 	 (PyObject *) Py_False );
1789 
1790 	return( Py_False );
1791 }
1792 
1793 /* Determines if the file entry has the directory entries index
1794  * Returns a Python object if successful or NULL on error
1795  */
pyfsntfs_file_entry_has_directory_entries_index(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)1796 PyObject *pyfsntfs_file_entry_has_directory_entries_index(
1797            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1798            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
1799 {
1800 	libcerror_error_t *error = NULL;
1801 	static char *function    = "pyfsntfs_file_entry_has_directory_entries_index";
1802 	int result               = 0;
1803 
1804 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
1805 
1806 	if( pyfsntfs_file_entry == NULL )
1807 	{
1808 		PyErr_Format(
1809 		 PyExc_ValueError,
1810 		 "%s: invalid file entry.",
1811 		 function );
1812 
1813 		return( NULL );
1814 	}
1815 	Py_BEGIN_ALLOW_THREADS
1816 
1817 	result = libfsntfs_file_entry_has_directory_entries_index(
1818 	          pyfsntfs_file_entry->file_entry,
1819 	          &error );
1820 
1821 	Py_END_ALLOW_THREADS
1822 
1823 	if( result == -1 )
1824 	{
1825 		pyfsntfs_error_raise(
1826 		 error,
1827 		 PyExc_IOError,
1828 		 "%s: unable to determine if file entry has directory entries index.",
1829 		 function );
1830 
1831 		libcerror_error_free(
1832 		 &error );
1833 
1834 		return( NULL );
1835 	}
1836 	if( result != 0 )
1837 	{
1838 		Py_IncRef(
1839 		 (PyObject *) Py_True );
1840 
1841 		return( Py_True );
1842 	}
1843 	Py_IncRef(
1844 	 (PyObject *) Py_False );
1845 
1846 	return( Py_False );
1847 }
1848 
1849 /* Determines if the file entry has the default data stream
1850  * Returns a Python object if successful or NULL on error
1851  */
pyfsntfs_file_entry_has_default_data_stream(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)1852 PyObject *pyfsntfs_file_entry_has_default_data_stream(
1853            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1854            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
1855 {
1856 	libcerror_error_t *error = NULL;
1857 	static char *function    = "pyfsntfs_file_entry_has_default_data_stream";
1858 	int result               = 0;
1859 
1860 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
1861 
1862 	if( pyfsntfs_file_entry == NULL )
1863 	{
1864 		PyErr_Format(
1865 		 PyExc_ValueError,
1866 		 "%s: invalid file entry.",
1867 		 function );
1868 
1869 		return( NULL );
1870 	}
1871 	Py_BEGIN_ALLOW_THREADS
1872 
1873 	result = libfsntfs_file_entry_has_default_data_stream(
1874 	          pyfsntfs_file_entry->file_entry,
1875 	          &error );
1876 
1877 	Py_END_ALLOW_THREADS
1878 
1879 	if( result == -1 )
1880 	{
1881 		pyfsntfs_error_raise(
1882 		 error,
1883 		 PyExc_IOError,
1884 		 "%s: unable to determine if file entry has default data stream.",
1885 		 function );
1886 
1887 		libcerror_error_free(
1888 		 &error );
1889 
1890 		return( NULL );
1891 	}
1892 	else if( result != 0 )
1893 	{
1894 		Py_IncRef(
1895 		 (PyObject *) Py_True );
1896 
1897 		return( Py_True );
1898 	}
1899 	Py_IncRef(
1900 	 (PyObject *) Py_False );
1901 
1902 	return( Py_False );
1903 }
1904 
1905 /* Retrieves the file reference
1906  * Returns a Python object if successful or NULL on error
1907  */
pyfsntfs_file_entry_get_file_reference(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)1908 PyObject *pyfsntfs_file_entry_get_file_reference(
1909            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1910            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
1911 {
1912 	libcerror_error_t *error = NULL;
1913 	PyObject *integer_object = NULL;
1914 	static char *function    = "pyfsntfs_file_entry_get_file_reference";
1915 	uint64_t file_reference  = 0;
1916 	int result               = 0;
1917 
1918 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
1919 
1920 	if( pyfsntfs_file_entry == NULL )
1921 	{
1922 		PyErr_Format(
1923 		 PyExc_ValueError,
1924 		 "%s: invalid file entry.",
1925 		 function );
1926 
1927 		return( NULL );
1928 	}
1929 	Py_BEGIN_ALLOW_THREADS
1930 
1931 	result = libfsntfs_file_entry_get_file_reference(
1932 	          pyfsntfs_file_entry->file_entry,
1933 	          &file_reference,
1934 	          &error );
1935 
1936 	Py_END_ALLOW_THREADS
1937 
1938 	if( result != 1 )
1939 	{
1940 		pyfsntfs_error_raise(
1941 		 error,
1942 		 PyExc_IOError,
1943 		 "%s: unable to retrieve file reference.",
1944 		 function );
1945 
1946 		libcerror_error_free(
1947 		 &error );
1948 
1949 		return( NULL );
1950 	}
1951 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
1952 	                  file_reference );
1953 
1954 	return( integer_object );
1955 }
1956 
1957 /* Retrieves the base record file reference
1958  * Returns a Python object if successful or NULL on error
1959  */
pyfsntfs_file_entry_get_base_record_file_reference(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)1960 PyObject *pyfsntfs_file_entry_get_base_record_file_reference(
1961            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
1962            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
1963 {
1964 	libcerror_error_t *error = NULL;
1965 	PyObject *integer_object = NULL;
1966 	static char *function    = "pyfsntfs_file_entry_get_base_record_file_reference";
1967 	uint64_t file_reference  = 0;
1968 	int result               = 0;
1969 
1970 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
1971 
1972 	if( pyfsntfs_file_entry == NULL )
1973 	{
1974 		PyErr_Format(
1975 		 PyExc_ValueError,
1976 		 "%s: invalid file entry.",
1977 		 function );
1978 
1979 		return( NULL );
1980 	}
1981 	Py_BEGIN_ALLOW_THREADS
1982 
1983 	result = libfsntfs_file_entry_get_base_record_file_reference(
1984 	          pyfsntfs_file_entry->file_entry,
1985 	          &file_reference,
1986 	          &error );
1987 
1988 	Py_END_ALLOW_THREADS
1989 
1990 	if( result != 1 )
1991 	{
1992 		pyfsntfs_error_raise(
1993 		 error,
1994 		 PyExc_IOError,
1995 		 "%s: unable to retrieve base record file reference.",
1996 		 function );
1997 
1998 		libcerror_error_free(
1999 		 &error );
2000 
2001 		return( NULL );
2002 	}
2003 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
2004 	                  file_reference );
2005 
2006 	return( integer_object );
2007 }
2008 
2009 /* Retrieves the parent file reference
2010  * Returns a Python object if successful or NULL on error
2011  */
pyfsntfs_file_entry_get_parent_file_reference(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2012 PyObject *pyfsntfs_file_entry_get_parent_file_reference(
2013            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2014            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2015 {
2016 	libcerror_error_t *error = NULL;
2017 	PyObject *integer_object = NULL;
2018 	static char *function    = "pyfsntfs_file_entry_get_parent_file_reference";
2019 	uint64_t file_reference  = 0;
2020 	int result               = 0;
2021 
2022 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2023 
2024 	if( pyfsntfs_file_entry == NULL )
2025 	{
2026 		PyErr_Format(
2027 		 PyExc_ValueError,
2028 		 "%s: invalid file entry.",
2029 		 function );
2030 
2031 		return( NULL );
2032 	}
2033 	Py_BEGIN_ALLOW_THREADS
2034 
2035 	result = libfsntfs_file_entry_get_parent_file_reference(
2036 	          pyfsntfs_file_entry->file_entry,
2037 	          &file_reference,
2038 	          &error );
2039 
2040 	Py_END_ALLOW_THREADS
2041 
2042 	if( result == -1 )
2043 	{
2044 		pyfsntfs_error_raise(
2045 		 error,
2046 		 PyExc_IOError,
2047 		 "%s: unable to retrieve parent file reference.",
2048 		 function );
2049 
2050 		libcerror_error_free(
2051 		 &error );
2052 
2053 		return( NULL );
2054 	}
2055 	else if( result == 0 )
2056 	{
2057 		Py_IncRef(
2058 		 Py_None );
2059 
2060 		return( Py_None );
2061 	}
2062 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
2063 	                  file_reference );
2064 
2065 	return( integer_object );
2066 }
2067 
2068 /* Retrieves the parent file reference for a specific $FILE_NAME attribute
2069  * Returns a Python object if successful or NULL on error
2070  */
pyfsntfs_file_entry_get_parent_file_reference_by_attribute_index(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)2071 PyObject *pyfsntfs_file_entry_get_parent_file_reference_by_attribute_index(
2072            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2073            PyObject *arguments,
2074            PyObject *keywords )
2075 {
2076 	libcerror_error_t *error    = NULL;
2077 	PyObject *integer_object    = NULL;
2078 	static char *function       = "pyfsntfs_file_entry_get_parent_file_reference_by_attribute_index";
2079 	static char *keyword_list[] = { "attribute_index", NULL };
2080 	uint64_t file_reference     = 0;
2081 	int attribute_index         = 0;
2082 	int result                  = 0;
2083 
2084 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2085 
2086 	if( pyfsntfs_file_entry == NULL )
2087 	{
2088 		PyErr_Format(
2089 		 PyExc_ValueError,
2090 		 "%s: invalid file entry.",
2091 		 function );
2092 
2093 		return( NULL );
2094 	}
2095 	if( PyArg_ParseTupleAndKeywords(
2096 	     arguments,
2097 	     keywords,
2098 	     "i",
2099 	     keyword_list,
2100 	     &attribute_index ) == 0 )
2101 	{
2102 		return( NULL );
2103 	}
2104 	Py_BEGIN_ALLOW_THREADS
2105 
2106 	result = libfsntfs_file_entry_get_parent_file_reference_by_attribute_index(
2107 	          pyfsntfs_file_entry->file_entry,
2108 	          attribute_index,
2109 	          &file_reference,
2110 	          &error );
2111 
2112 	Py_END_ALLOW_THREADS
2113 
2114 	if( result != 1 )
2115 	{
2116 		pyfsntfs_error_raise(
2117 		 error,
2118 		 PyExc_IOError,
2119 		 "%s: unable to retrieve parent file reference from attribute: %d.",
2120 		 function,
2121 		 attribute_index );
2122 
2123 		libcerror_error_free(
2124 		 &error );
2125 
2126 		return( NULL );
2127 	}
2128 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
2129 	                  file_reference );
2130 
2131 	return( integer_object );
2132 }
2133 
2134 /* Retrieves the journal sequence number
2135  * Returns a Python object if successful or NULL on error
2136  */
pyfsntfs_file_entry_get_journal_sequence_number(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2137 PyObject *pyfsntfs_file_entry_get_journal_sequence_number(
2138            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2139            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2140 {
2141 	libcerror_error_t *error         = NULL;
2142 	PyObject *integer_object         = NULL;
2143 	static char *function            = "pyfsntfs_file_entry_get_journal_sequence_number";
2144 	uint64_t journal_sequence_number = 0;
2145 	int result                       = 0;
2146 
2147 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2148 
2149 	if( pyfsntfs_file_entry == NULL )
2150 	{
2151 		PyErr_Format(
2152 		 PyExc_ValueError,
2153 		 "%s: invalid file entry.",
2154 		 function );
2155 
2156 		return( NULL );
2157 	}
2158 	Py_BEGIN_ALLOW_THREADS
2159 
2160 	result = libfsntfs_file_entry_get_journal_sequence_number(
2161 	          pyfsntfs_file_entry->file_entry,
2162 	          &journal_sequence_number,
2163 	          &error );
2164 
2165 	Py_END_ALLOW_THREADS
2166 
2167 	if( result != 1 )
2168 	{
2169 		pyfsntfs_error_raise(
2170 		 error,
2171 		 PyExc_IOError,
2172 		 "%s: unable to retrieve journal sequence number.",
2173 		 function );
2174 
2175 		libcerror_error_free(
2176 		 &error );
2177 
2178 		return( NULL );
2179 	}
2180 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
2181 	                  journal_sequence_number );
2182 
2183 	return( integer_object );
2184 }
2185 
2186 /* Retrieves the creation date and time
2187  * Returns a Python object if successful or NULL on error
2188  */
pyfsntfs_file_entry_get_creation_time(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2189 PyObject *pyfsntfs_file_entry_get_creation_time(
2190            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2191            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2192 {
2193 	libcerror_error_t *error   = NULL;
2194 	PyObject *date_time_object = NULL;
2195 	static char *function      = "pyfsntfs_file_entry_get_creation_time";
2196 	uint64_t filetime          = 0;
2197 	int result                 = 0;
2198 
2199 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2200 
2201 	if( pyfsntfs_file_entry == NULL )
2202 	{
2203 		PyErr_Format(
2204 		 PyExc_ValueError,
2205 		 "%s: invalid file entry.",
2206 		 function );
2207 
2208 		return( NULL );
2209 	}
2210 	Py_BEGIN_ALLOW_THREADS
2211 
2212 	result = libfsntfs_file_entry_get_creation_time(
2213 	          pyfsntfs_file_entry->file_entry,
2214 	          &filetime,
2215 	          &error );
2216 
2217 	Py_END_ALLOW_THREADS
2218 
2219 	if( result == -1 )
2220 	{
2221 		pyfsntfs_error_raise(
2222 		 error,
2223 		 PyExc_IOError,
2224 		 "%s: unable to retrieve creation time.",
2225 		 function );
2226 
2227 		libcerror_error_free(
2228 		 &error );
2229 
2230 		return( NULL );
2231 	}
2232 	else if( result == 0 )
2233 	{
2234 		Py_IncRef(
2235 		 Py_None );
2236 
2237 		return( Py_None );
2238 	}
2239 	date_time_object = pyfsntfs_datetime_new_from_filetime(
2240 	                    filetime );
2241 
2242 	return( date_time_object );
2243 }
2244 
2245 /* Retrieves the creation date and time as an integer
2246  * Returns a Python object if successful or NULL on error
2247  */
pyfsntfs_file_entry_get_creation_time_as_integer(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2248 PyObject *pyfsntfs_file_entry_get_creation_time_as_integer(
2249            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2250            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2251 {
2252 	libcerror_error_t *error = NULL;
2253 	PyObject *integer_object = NULL;
2254 	static char *function    = "pyfsntfs_file_entry_get_creation_time_as_integer";
2255 	uint64_t filetime        = 0;
2256 	int result               = 0;
2257 
2258 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2259 
2260 	if( pyfsntfs_file_entry == NULL )
2261 	{
2262 		PyErr_Format(
2263 		 PyExc_ValueError,
2264 		 "%s: invalid file entry.",
2265 		 function );
2266 
2267 		return( NULL );
2268 	}
2269 	Py_BEGIN_ALLOW_THREADS
2270 
2271 	result = libfsntfs_file_entry_get_creation_time(
2272 	          pyfsntfs_file_entry->file_entry,
2273 	          &filetime,
2274 	          &error );
2275 
2276 	Py_END_ALLOW_THREADS
2277 
2278 	if( result == -1 )
2279 	{
2280 		pyfsntfs_error_raise(
2281 		 error,
2282 		 PyExc_IOError,
2283 		 "%s: unable to retrieve creation time.",
2284 		 function );
2285 
2286 		libcerror_error_free(
2287 		 &error );
2288 
2289 		return( NULL );
2290 	}
2291 	else if( result == 0 )
2292 	{
2293 		Py_IncRef(
2294 		 Py_None );
2295 
2296 		return( Py_None );
2297 	}
2298 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
2299 	                  filetime );
2300 
2301 	return( integer_object );
2302 }
2303 
2304 /* Retrieves the modification date and time
2305  * Returns a Python object if successful or NULL on error
2306  */
pyfsntfs_file_entry_get_modification_time(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2307 PyObject *pyfsntfs_file_entry_get_modification_time(
2308            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2309            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2310 {
2311 	libcerror_error_t *error   = NULL;
2312 	PyObject *date_time_object = NULL;
2313 	static char *function      = "pyfsntfs_file_entry_get_modification_time";
2314 	uint64_t filetime          = 0;
2315 	int result                 = 0;
2316 
2317 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2318 
2319 	if( pyfsntfs_file_entry == NULL )
2320 	{
2321 		PyErr_Format(
2322 		 PyExc_ValueError,
2323 		 "%s: invalid file entry.",
2324 		 function );
2325 
2326 		return( NULL );
2327 	}
2328 	Py_BEGIN_ALLOW_THREADS
2329 
2330 	result = libfsntfs_file_entry_get_modification_time(
2331 	          pyfsntfs_file_entry->file_entry,
2332 	          &filetime,
2333 	          &error );
2334 
2335 	Py_END_ALLOW_THREADS
2336 
2337 	if( result == -1 )
2338 	{
2339 		pyfsntfs_error_raise(
2340 		 error,
2341 		 PyExc_IOError,
2342 		 "%s: unable to retrieve modification time.",
2343 		 function );
2344 
2345 		libcerror_error_free(
2346 		 &error );
2347 
2348 		return( NULL );
2349 	}
2350 	else if( result == 0 )
2351 	{
2352 		Py_IncRef(
2353 		 Py_None );
2354 
2355 		return( Py_None );
2356 	}
2357 	date_time_object = pyfsntfs_datetime_new_from_filetime(
2358 	                    filetime );
2359 
2360 	return( date_time_object );
2361 }
2362 
2363 /* Retrieves the modification date and time as an integer
2364  * Returns a Python object if successful or NULL on error
2365  */
pyfsntfs_file_entry_get_modification_time_as_integer(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2366 PyObject *pyfsntfs_file_entry_get_modification_time_as_integer(
2367            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2368            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2369 {
2370 	libcerror_error_t *error = NULL;
2371 	PyObject *integer_object = NULL;
2372 	static char *function    = "pyfsntfs_file_entry_get_modification_time_as_integer";
2373 	uint64_t filetime        = 0;
2374 	int result               = 0;
2375 
2376 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2377 
2378 	if( pyfsntfs_file_entry == NULL )
2379 	{
2380 		PyErr_Format(
2381 		 PyExc_ValueError,
2382 		 "%s: invalid file entry.",
2383 		 function );
2384 
2385 		return( NULL );
2386 	}
2387 	Py_BEGIN_ALLOW_THREADS
2388 
2389 	result = libfsntfs_file_entry_get_modification_time(
2390 	          pyfsntfs_file_entry->file_entry,
2391 	          &filetime,
2392 	          &error );
2393 
2394 	Py_END_ALLOW_THREADS
2395 
2396 	if( result == -1 )
2397 	{
2398 		pyfsntfs_error_raise(
2399 		 error,
2400 		 PyExc_IOError,
2401 		 "%s: unable to retrieve modification time.",
2402 		 function );
2403 
2404 		libcerror_error_free(
2405 		 &error );
2406 
2407 		return( NULL );
2408 	}
2409 	else if( result == 0 )
2410 	{
2411 		Py_IncRef(
2412 		 Py_None );
2413 
2414 		return( Py_None );
2415 	}
2416 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
2417 	                  filetime );
2418 
2419 	return( integer_object );
2420 }
2421 
2422 /* Retrieves the access date and time
2423  * Returns a Python object if successful or NULL on error
2424  */
pyfsntfs_file_entry_get_access_time(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2425 PyObject *pyfsntfs_file_entry_get_access_time(
2426            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2427            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2428 {
2429 	libcerror_error_t *error   = NULL;
2430 	PyObject *date_time_object = NULL;
2431 	static char *function      = "pyfsntfs_file_entry_get_access_time";
2432 	uint64_t filetime          = 0;
2433 	int result                 = 0;
2434 
2435 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2436 
2437 	if( pyfsntfs_file_entry == NULL )
2438 	{
2439 		PyErr_Format(
2440 		 PyExc_ValueError,
2441 		 "%s: invalid file entry.",
2442 		 function );
2443 
2444 		return( NULL );
2445 	}
2446 	Py_BEGIN_ALLOW_THREADS
2447 
2448 	result = libfsntfs_file_entry_get_access_time(
2449 	          pyfsntfs_file_entry->file_entry,
2450 	          &filetime,
2451 	          &error );
2452 
2453 	Py_END_ALLOW_THREADS
2454 
2455 	if( result == -1 )
2456 	{
2457 		pyfsntfs_error_raise(
2458 		 error,
2459 		 PyExc_IOError,
2460 		 "%s: unable to retrieve access time.",
2461 		 function );
2462 
2463 		libcerror_error_free(
2464 		 &error );
2465 
2466 		return( NULL );
2467 	}
2468 	else if( result == 0 )
2469 	{
2470 		Py_IncRef(
2471 		 Py_None );
2472 
2473 		return( Py_None );
2474 	}
2475 	date_time_object = pyfsntfs_datetime_new_from_filetime(
2476 	                    filetime );
2477 
2478 	return( date_time_object );
2479 }
2480 
2481 /* Retrieves the access date and time as an integer
2482  * Returns a Python object if successful or NULL on error
2483  */
pyfsntfs_file_entry_get_access_time_as_integer(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2484 PyObject *pyfsntfs_file_entry_get_access_time_as_integer(
2485            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2486            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2487 {
2488 	libcerror_error_t *error = NULL;
2489 	PyObject *integer_object = NULL;
2490 	static char *function    = "pyfsntfs_file_entry_get_access_time_as_integer";
2491 	uint64_t filetime        = 0;
2492 	int result               = 0;
2493 
2494 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2495 
2496 	if( pyfsntfs_file_entry == NULL )
2497 	{
2498 		PyErr_Format(
2499 		 PyExc_ValueError,
2500 		 "%s: invalid file entry.",
2501 		 function );
2502 
2503 		return( NULL );
2504 	}
2505 	Py_BEGIN_ALLOW_THREADS
2506 
2507 	result = libfsntfs_file_entry_get_access_time(
2508 	          pyfsntfs_file_entry->file_entry,
2509 	          &filetime,
2510 	          &error );
2511 
2512 	Py_END_ALLOW_THREADS
2513 
2514 	if( result == -1 )
2515 	{
2516 		pyfsntfs_error_raise(
2517 		 error,
2518 		 PyExc_IOError,
2519 		 "%s: unable to retrieve access time.",
2520 		 function );
2521 
2522 		libcerror_error_free(
2523 		 &error );
2524 
2525 		return( NULL );
2526 	}
2527 	else if( result == 0 )
2528 	{
2529 		Py_IncRef(
2530 		 Py_None );
2531 
2532 		return( Py_None );
2533 	}
2534 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
2535 	                  filetime );
2536 
2537 	return( integer_object );
2538 }
2539 
2540 /* Retrieves the entry modification date and time
2541  * Returns a Python object if successful or NULL on error
2542  */
pyfsntfs_file_entry_get_entry_modification_time(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2543 PyObject *pyfsntfs_file_entry_get_entry_modification_time(
2544            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2545            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2546 {
2547 	libcerror_error_t *error   = NULL;
2548 	PyObject *date_time_object = NULL;
2549 	static char *function      = "pyfsntfs_file_entry_get_entry_modification_time";
2550 	uint64_t filetime          = 0;
2551 	int result                 = 0;
2552 
2553 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2554 
2555 	if( pyfsntfs_file_entry == NULL )
2556 	{
2557 		PyErr_Format(
2558 		 PyExc_ValueError,
2559 		 "%s: invalid file entry.",
2560 		 function );
2561 
2562 		return( NULL );
2563 	}
2564 	Py_BEGIN_ALLOW_THREADS
2565 
2566 	result = libfsntfs_file_entry_get_entry_modification_time(
2567 	          pyfsntfs_file_entry->file_entry,
2568 	          &filetime,
2569 	          &error );
2570 
2571 	Py_END_ALLOW_THREADS
2572 
2573 	if( result == -1 )
2574 	{
2575 		pyfsntfs_error_raise(
2576 		 error,
2577 		 PyExc_IOError,
2578 		 "%s: unable to retrieve entry modification time.",
2579 		 function );
2580 
2581 		libcerror_error_free(
2582 		 &error );
2583 
2584 		return( NULL );
2585 	}
2586 	else if( result == 0 )
2587 	{
2588 		Py_IncRef(
2589 		 Py_None );
2590 
2591 		return( Py_None );
2592 	}
2593 	date_time_object = pyfsntfs_datetime_new_from_filetime(
2594 	                    filetime );
2595 
2596 	return( date_time_object );
2597 }
2598 
2599 /* Retrieves the entry modification date and time as an integer
2600  * Returns a Python object if successful or NULL on error
2601  */
pyfsntfs_file_entry_get_entry_modification_time_as_integer(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2602 PyObject *pyfsntfs_file_entry_get_entry_modification_time_as_integer(
2603            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2604            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2605 {
2606 	libcerror_error_t *error = NULL;
2607 	PyObject *integer_object = NULL;
2608 	static char *function    = "pyfsntfs_file_entry_get_entry_modification_time_as_integer";
2609 	uint64_t filetime        = 0;
2610 	int result               = 0;
2611 
2612 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2613 
2614 	if( pyfsntfs_file_entry == NULL )
2615 	{
2616 		PyErr_Format(
2617 		 PyExc_ValueError,
2618 		 "%s: invalid file entry.",
2619 		 function );
2620 
2621 		return( NULL );
2622 	}
2623 	Py_BEGIN_ALLOW_THREADS
2624 
2625 	result = libfsntfs_file_entry_get_entry_modification_time(
2626 	          pyfsntfs_file_entry->file_entry,
2627 	          &filetime,
2628 	          &error );
2629 
2630 	Py_END_ALLOW_THREADS
2631 
2632 	if( result == -1 )
2633 	{
2634 		pyfsntfs_error_raise(
2635 		 error,
2636 		 PyExc_IOError,
2637 		 "%s: unable to retrieve entry modification time.",
2638 		 function );
2639 
2640 		libcerror_error_free(
2641 		 &error );
2642 
2643 		return( NULL );
2644 	}
2645 	else if( result == 0 )
2646 	{
2647 		Py_IncRef(
2648 		 Py_None );
2649 
2650 		return( Py_None );
2651 	}
2652 	integer_object = pyfsntfs_integer_signed_new_from_64bit(
2653 	                  filetime );
2654 
2655 	return( integer_object );
2656 }
2657 
2658 /* Retrieves the name
2659  * Returns a Python object if successful or NULL on error
2660  */
pyfsntfs_file_entry_get_name(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2661 PyObject *pyfsntfs_file_entry_get_name(
2662            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2663            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2664 {
2665 	libcerror_error_t *error = NULL;
2666 	PyObject *string_object  = NULL;
2667 	const char *errors       = NULL;
2668 	uint8_t *name            = NULL;
2669 	static char *function    = "pyfsntfs_file_entry_get_name";
2670 	size_t name_size         = 0;
2671 	int result               = 0;
2672 
2673 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2674 
2675 	if( pyfsntfs_file_entry == NULL )
2676 	{
2677 		PyErr_Format(
2678 		 PyExc_ValueError,
2679 		 "%s: invalid file entry.",
2680 		 function );
2681 
2682 		return( NULL );
2683 	}
2684 	Py_BEGIN_ALLOW_THREADS
2685 
2686 	result = libfsntfs_file_entry_get_utf8_name_size(
2687 	          pyfsntfs_file_entry->file_entry,
2688 	          &name_size,
2689 	          &error );
2690 
2691 	Py_END_ALLOW_THREADS
2692 
2693 	if( result == -1 )
2694 	{
2695 		pyfsntfs_error_raise(
2696 		 error,
2697 		 PyExc_IOError,
2698 		 "%s: unable to retrieve name size.",
2699 		 function );
2700 
2701 		libcerror_error_free(
2702 		 &error );
2703 
2704 		goto on_error;
2705 	}
2706 	else if( ( result == 0 )
2707 	      || ( name_size == 0 ) )
2708 	{
2709 		Py_IncRef(
2710 		 Py_None );
2711 
2712 		return( Py_None );
2713 	}
2714 	name = (uint8_t *) PyMem_Malloc(
2715 	                    sizeof( uint8_t ) * name_size );
2716 
2717 	if( name == NULL )
2718 	{
2719 		PyErr_Format(
2720 		 PyExc_IOError,
2721 		 "%s: unable to create name.",
2722 		 function );
2723 
2724 		goto on_error;
2725 	}
2726 	Py_BEGIN_ALLOW_THREADS
2727 
2728 	result = libfsntfs_file_entry_get_utf8_name(
2729 		  pyfsntfs_file_entry->file_entry,
2730 		  name,
2731 		  name_size,
2732 		  &error );
2733 
2734 	Py_END_ALLOW_THREADS
2735 
2736 	if( result != 1 )
2737 	{
2738 		pyfsntfs_error_raise(
2739 		 error,
2740 		 PyExc_IOError,
2741 		 "%s: unable to retrieve name.",
2742 		 function );
2743 
2744 		libcerror_error_free(
2745 		 &error );
2746 
2747 		goto on_error;
2748 	}
2749 	/* Pass the string length to PyUnicode_DecodeUTF8
2750 	 * otherwise it makes the end of string character is part
2751 	 * of the string
2752 	 */
2753 	string_object = PyUnicode_DecodeUTF8(
2754 			 (char *) name,
2755 			 (Py_ssize_t) name_size - 1,
2756 			 errors );
2757 
2758 	PyMem_Free(
2759 	 name );
2760 
2761 	return( string_object );
2762 
2763 on_error:
2764 	if( name != NULL )
2765 	{
2766 		PyMem_Free(
2767 		 name );
2768 	}
2769 	return( NULL );
2770 }
2771 
2772 /* Retrieves the name attribute index
2773  * Returns a Python object if successful or NULL on error
2774  */
pyfsntfs_file_entry_get_name_attribute_index(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2775 PyObject *pyfsntfs_file_entry_get_name_attribute_index(
2776            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2777            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2778 {
2779 	libcerror_error_t *error = NULL;
2780 	PyObject *integer_object = NULL;
2781 	static char *function    = "pyfsntfs_file_entry_get_name_attribute_index";
2782 	int attribute_index      = 0;
2783 	int result               = 0;
2784 
2785 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2786 
2787 	if( pyfsntfs_file_entry == NULL )
2788 	{
2789 		PyErr_Format(
2790 		 PyExc_ValueError,
2791 		 "%s: invalid file entry.",
2792 		 function );
2793 
2794 		return( NULL );
2795 	}
2796 	Py_BEGIN_ALLOW_THREADS
2797 
2798 	result = libfsntfs_file_entry_get_name_attribute_index(
2799 	          pyfsntfs_file_entry->file_entry,
2800 	          &attribute_index,
2801 	          &error );
2802 
2803 	Py_END_ALLOW_THREADS
2804 
2805 	if( result == -1 )
2806 	{
2807 		pyfsntfs_error_raise(
2808 		 error,
2809 		 PyExc_IOError,
2810 		 "%s: unable to retrieve name attribute index.",
2811 		 function );
2812 
2813 		libcerror_error_free(
2814 		 &error );
2815 
2816 		return( NULL );
2817 	}
2818 	else if( result == 0 )
2819 	{
2820 		Py_IncRef(
2821 		 Py_None );
2822 
2823 		return( Py_None );
2824 	}
2825 #if PY_MAJOR_VERSION >= 3
2826 	integer_object = PyLong_FromLong(
2827 	                  (long) attribute_index );
2828 #else
2829 	integer_object = PyInt_FromLong(
2830 	                  (long) attribute_index );
2831 #endif
2832 	return( integer_object );
2833 }
2834 
2835 /* Retrieves the name for a specific $FILE_NAME attribute
2836  * Returns a Python object if successful or NULL on error
2837  */
pyfsntfs_file_entry_get_name_by_attribute_index(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)2838 PyObject *pyfsntfs_file_entry_get_name_by_attribute_index(
2839            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2840            PyObject *arguments,
2841            PyObject *keywords )
2842 {
2843 	libcerror_error_t *error    = NULL;
2844 	PyObject *string_object     = NULL;
2845 	const char *errors          = NULL;
2846 	uint8_t *name               = NULL;
2847 	static char *function       = "pyfsntfs_file_entry_get_name_by_attribute_index";
2848 	static char *keyword_list[] = { "attribute_index", NULL };
2849 	size_t name_size            = 0;
2850 	int attribute_index         = 0;
2851 	int result                  = 0;
2852 
2853 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2854 
2855 	if( pyfsntfs_file_entry == NULL )
2856 	{
2857 		PyErr_Format(
2858 		 PyExc_ValueError,
2859 		 "%s: invalid file entry.",
2860 		 function );
2861 
2862 		return( NULL );
2863 	}
2864 	if( PyArg_ParseTupleAndKeywords(
2865 	     arguments,
2866 	     keywords,
2867 	     "i",
2868 	     keyword_list,
2869 	     &attribute_index ) == 0 )
2870 	{
2871 		return( NULL );
2872 	}
2873 	Py_BEGIN_ALLOW_THREADS
2874 
2875 	result = libfsntfs_file_entry_get_utf8_name_size_by_attribute_index(
2876 	          pyfsntfs_file_entry->file_entry,
2877 	          attribute_index,
2878 	          &name_size,
2879 	          &error );
2880 
2881 	Py_END_ALLOW_THREADS
2882 
2883 	if( result != 1 )
2884 	{
2885 		pyfsntfs_error_raise(
2886 		 error,
2887 		 PyExc_IOError,
2888 		 "%s: unable to retrieve name size.",
2889 		 function );
2890 
2891 		libcerror_error_free(
2892 		 &error );
2893 
2894 		goto on_error;
2895 	}
2896 	else if( name_size == 0 )
2897 	{
2898 		Py_IncRef(
2899 		 Py_None );
2900 
2901 		return( Py_None );
2902 	}
2903 	name = (uint8_t *) PyMem_Malloc(
2904 	                    sizeof( uint8_t ) * name_size );
2905 
2906 	if( name == NULL )
2907 	{
2908 		PyErr_Format(
2909 		 PyExc_IOError,
2910 		 "%s: unable to create name.",
2911 		 function );
2912 
2913 		goto on_error;
2914 	}
2915 	Py_BEGIN_ALLOW_THREADS
2916 
2917 	result = libfsntfs_file_entry_get_utf8_name_by_attribute_index(
2918 		  pyfsntfs_file_entry->file_entry,
2919 	          attribute_index,
2920 		  name,
2921 		  name_size,
2922 		  &error );
2923 
2924 	Py_END_ALLOW_THREADS
2925 
2926 	if( result != 1 )
2927 	{
2928 		pyfsntfs_error_raise(
2929 		 error,
2930 		 PyExc_IOError,
2931 		 "%s: unable to retrieve name.",
2932 		 function );
2933 
2934 		libcerror_error_free(
2935 		 &error );
2936 
2937 		goto on_error;
2938 	}
2939 	/* Pass the string length to PyUnicode_DecodeUTF8
2940 	 * otherwise it makes the end of string character is part
2941 	 * of the string
2942 	 */
2943 	string_object = PyUnicode_DecodeUTF8(
2944 			 (char *) name,
2945 			 (Py_ssize_t) name_size - 1,
2946 			 errors );
2947 
2948 	PyMem_Free(
2949 	 name );
2950 
2951 	return( string_object );
2952 
2953 on_error:
2954 	if( name != NULL )
2955 	{
2956 		PyMem_Free(
2957 		 name );
2958 	}
2959 	return( NULL );
2960 }
2961 
2962 /* Retrieves the file attribute flags
2963  * Returns a Python object if successful or NULL on error
2964  */
pyfsntfs_file_entry_get_file_attribute_flags(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)2965 PyObject *pyfsntfs_file_entry_get_file_attribute_flags(
2966            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
2967            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
2968 {
2969 	libcerror_error_t *error      = NULL;
2970 	PyObject *integer_object      = NULL;
2971 	static char *function         = "pyfsntfs_file_entry_get_file_entry_flags";
2972 	uint32_t file_attribute_flags = 0;
2973 	int result                    = 0;
2974 
2975 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
2976 
2977 	if( pyfsntfs_file_entry == NULL )
2978 	{
2979 		PyErr_Format(
2980 		 PyExc_ValueError,
2981 		 "%s: invalid file entry.",
2982 		 function );
2983 
2984 		return( NULL );
2985 	}
2986 	Py_BEGIN_ALLOW_THREADS
2987 
2988 	result = libfsntfs_file_entry_get_file_attribute_flags(
2989 	          pyfsntfs_file_entry->file_entry,
2990 	          &file_attribute_flags,
2991 	          &error );
2992 
2993 	Py_END_ALLOW_THREADS
2994 
2995 	if( result == -1 )
2996 	{
2997 		pyfsntfs_error_raise(
2998 		 error,
2999 		 PyExc_IOError,
3000 		 "%s: unable to retrieve file attribute flags.",
3001 		 function );
3002 
3003 		libcerror_error_free(
3004 		 &error );
3005 
3006 		return( NULL );
3007 	}
3008 	else if( result == 0 )
3009 	{
3010 		Py_IncRef(
3011 		 Py_None );
3012 
3013 		return( Py_None );
3014 	}
3015 	integer_object = pyfsntfs_integer_unsigned_new_from_64bit(
3016 	                  (uint64_t) file_attribute_flags );
3017 
3018 	return( integer_object );
3019 }
3020 
3021 /* Retrieves the path hint for a specific $FILE_NAME attribute
3022  * Returns a Python object if successful or NULL on error
3023  */
pyfsntfs_file_entry_get_path_hint(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)3024 PyObject *pyfsntfs_file_entry_get_path_hint(
3025            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3026            PyObject *arguments,
3027            PyObject *keywords )
3028 {
3029 	libcerror_error_t *error    = NULL;
3030 	PyObject *string_object     = NULL;
3031 	const char *errors          = NULL;
3032 	uint8_t *path               = NULL;
3033 	static char *function       = "pyfsntfs_file_entry_get_path_hint";
3034 	static char *keyword_list[] = { "attribute_index", NULL };
3035 	size_t path_size            = 0;
3036 	int attribute_index         = 0;
3037 	int result                  = 0;
3038 
3039 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
3040 
3041 	if( pyfsntfs_file_entry == NULL )
3042 	{
3043 		PyErr_Format(
3044 		 PyExc_ValueError,
3045 		 "%s: invalid file entry.",
3046 		 function );
3047 
3048 		return( NULL );
3049 	}
3050 	if( PyArg_ParseTupleAndKeywords(
3051 	     arguments,
3052 	     keywords,
3053 	     "i",
3054 	     keyword_list,
3055 	     &attribute_index ) == 0 )
3056 	{
3057 		return( NULL );
3058 	}
3059 	Py_BEGIN_ALLOW_THREADS
3060 
3061 	result = libfsntfs_file_entry_get_utf8_path_hint_size(
3062 	          pyfsntfs_file_entry->file_entry,
3063 	          attribute_index,
3064 	          &path_size,
3065 	          &error );
3066 
3067 	Py_END_ALLOW_THREADS
3068 
3069 	if( result != 1 )
3070 	{
3071 		pyfsntfs_error_raise(
3072 		 error,
3073 		 PyExc_IOError,
3074 		 "%s: unable to retrieve path size.",
3075 		 function );
3076 
3077 		libcerror_error_free(
3078 		 &error );
3079 
3080 		goto on_error;
3081 	}
3082 	else if( path_size == 0 )
3083 	{
3084 		Py_IncRef(
3085 		 Py_None );
3086 
3087 		return( Py_None );
3088 	}
3089 	path = (uint8_t *) PyMem_Malloc(
3090 	                    sizeof( uint8_t ) * path_size );
3091 
3092 	if( path == NULL )
3093 	{
3094 		PyErr_Format(
3095 		 PyExc_IOError,
3096 		 "%s: unable to create path.",
3097 		 function );
3098 
3099 		goto on_error;
3100 	}
3101 	Py_BEGIN_ALLOW_THREADS
3102 
3103 	result = libfsntfs_file_entry_get_utf8_path_hint(
3104 		  pyfsntfs_file_entry->file_entry,
3105 	          attribute_index,
3106 		  path,
3107 		  path_size,
3108 		  &error );
3109 
3110 	Py_END_ALLOW_THREADS
3111 
3112 	if( result != 1 )
3113 	{
3114 		pyfsntfs_error_raise(
3115 		 error,
3116 		 PyExc_IOError,
3117 		 "%s: unable to retrieve path.",
3118 		 function );
3119 
3120 		libcerror_error_free(
3121 		 &error );
3122 
3123 		goto on_error;
3124 	}
3125 	/* Pass the string length to PyUnicode_DecodeUTF8
3126 	 * otherwise it makes the end of string character is part
3127 	 * of the string
3128 	 */
3129 	string_object = PyUnicode_DecodeUTF8(
3130 			 (char *) path,
3131 			 (Py_ssize_t) path_size - 1,
3132 			 errors );
3133 
3134 	PyMem_Free(
3135 	 path );
3136 
3137 	return( string_object );
3138 
3139 on_error:
3140 	if( path != NULL )
3141 	{
3142 		PyMem_Free(
3143 		 path );
3144 	}
3145 	return( NULL );
3146 }
3147 
3148 /* Retrieves the symbolic link target
3149  * Returns a Python object if successful or NULL on error
3150  */
pyfsntfs_file_entry_get_symbolic_link_target(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)3151 PyObject *pyfsntfs_file_entry_get_symbolic_link_target(
3152            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3153            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
3154 {
3155 	libcerror_error_t *error = NULL;
3156 	PyObject *string_object  = NULL;
3157 	const char *errors       = NULL;
3158 	uint8_t *name            = NULL;
3159 	static char *function    = "pyfsntfs_file_entry_get_symbolic_link_target";
3160 	size_t name_size         = 0;
3161 	int result               = 0;
3162 
3163 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
3164 
3165 	if( pyfsntfs_file_entry == NULL )
3166 	{
3167 		PyErr_Format(
3168 		 PyExc_ValueError,
3169 		 "%s: invalid file entry.",
3170 		 function );
3171 
3172 		return( NULL );
3173 	}
3174 	Py_BEGIN_ALLOW_THREADS
3175 
3176 	result = libfsntfs_file_entry_get_utf8_symbolic_link_target_size(
3177 	          pyfsntfs_file_entry->file_entry,
3178 	          &name_size,
3179 	          &error );
3180 
3181 	Py_END_ALLOW_THREADS
3182 
3183 	if( result == -1 )
3184 	{
3185 		pyfsntfs_error_raise(
3186 		 error,
3187 		 PyExc_IOError,
3188 		 "%s: unable to retrieve symbolic link target size.",
3189 		 function );
3190 
3191 		libcerror_error_free(
3192 		 &error );
3193 
3194 		goto on_error;
3195 	}
3196 	else if( ( result == 0 )
3197 	      || ( name_size == 0 ) )
3198 	{
3199 		Py_IncRef(
3200 		 Py_None );
3201 
3202 		return( Py_None );
3203 	}
3204 	name = (uint8_t *) PyMem_Malloc(
3205 	                    sizeof( uint8_t ) * name_size );
3206 
3207 	if( name == NULL )
3208 	{
3209 		PyErr_Format(
3210 		 PyExc_IOError,
3211 		 "%s: unable to create name.",
3212 		 function );
3213 
3214 		goto on_error;
3215 	}
3216 	Py_BEGIN_ALLOW_THREADS
3217 
3218 	result = libfsntfs_file_entry_get_utf8_symbolic_link_target(
3219 		  pyfsntfs_file_entry->file_entry,
3220 		  name,
3221 		  name_size,
3222 		  &error );
3223 
3224 	Py_END_ALLOW_THREADS
3225 
3226 	if( result != 1 )
3227 	{
3228 		pyfsntfs_error_raise(
3229 		 error,
3230 		 PyExc_IOError,
3231 		 "%s: unable to retrieve symbolic link target.",
3232 		 function );
3233 
3234 		libcerror_error_free(
3235 		 &error );
3236 
3237 		goto on_error;
3238 	}
3239 	/* Pass the string length to PyUnicode_DecodeUTF8
3240 	 * otherwise it makes the end of string character is part
3241 	 * of the string
3242 	 */
3243 	string_object = PyUnicode_DecodeUTF8(
3244 			 (char *) name,
3245 			 (Py_ssize_t) name_size - 1,
3246 			 errors );
3247 
3248 	PyMem_Free(
3249 	 name );
3250 
3251 	return( string_object );
3252 
3253 on_error:
3254 	if( name != NULL )
3255 	{
3256 		PyMem_Free(
3257 		 name );
3258 	}
3259 	return( NULL );
3260 }
3261 
3262 /* Retrieves the security descriptor data
3263  * Returns a Python object if successful or NULL on error
3264  */
pyfsntfs_file_entry_get_security_descriptor_data(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)3265 PyObject *pyfsntfs_file_entry_get_security_descriptor_data(
3266            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3267            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
3268 {
3269 	libcerror_error_t *error            = NULL;
3270 	PyObject *string_object             = NULL;
3271 	static char *function               = "pyfsntfs_file_entry_get_security_descriptor_data";
3272 	char *security_desciptor_data       = NULL;
3273 	size_t security_desciptor_data_size = 0;
3274 	int result                          = 0;
3275 
3276 	if( pyfsntfs_file_entry == NULL )
3277 	{
3278 		PyErr_Format(
3279 		 PyExc_ValueError,
3280 		 "%s: invalid file entry.",
3281 		 function );
3282 
3283 		return( NULL );
3284 	}
3285 	Py_BEGIN_ALLOW_THREADS
3286 
3287 	result = libfsntfs_file_entry_get_security_descriptor_size(
3288 	          pyfsntfs_file_entry->file_entry,
3289 	          &security_desciptor_data_size,
3290 	          &error );
3291 
3292 	Py_END_ALLOW_THREADS
3293 
3294 	if( result == -1 )
3295 	{
3296 		pyfsntfs_error_raise(
3297 		 error,
3298 		 PyExc_IOError,
3299 		 "%s: unable to determine security descriptor data size.",
3300 		 function );
3301 
3302 		libcerror_error_free(
3303 		 &error );
3304 
3305 		return( NULL );
3306 	}
3307 	else if( result == 0 )
3308 	{
3309 		Py_IncRef(
3310 		 Py_None );
3311 
3312 		return( Py_None );
3313 	}
3314 #if PY_MAJOR_VERSION >= 3
3315 	string_object = PyBytes_FromStringAndSize(
3316 	                 NULL,
3317 	                 security_desciptor_data_size );
3318 
3319 	security_desciptor_data = PyBytes_AsString(
3320 	                           string_object );
3321 #else
3322 	/* Note that a size of 0 is not supported
3323 	 */
3324 	string_object = PyString_FromStringAndSize(
3325 	                 NULL,
3326 	                 security_desciptor_data_size );
3327 
3328 	security_desciptor_data = PyString_AsString(
3329 	                           string_object );
3330 #endif
3331 	Py_BEGIN_ALLOW_THREADS
3332 
3333 	result = libfsntfs_file_entry_get_security_descriptor(
3334 	          pyfsntfs_file_entry->file_entry,
3335 	          (uint8_t *) security_desciptor_data,
3336 	          security_desciptor_data_size,
3337 	          &error );
3338 
3339 	Py_END_ALLOW_THREADS
3340 
3341 	if( result != 1 )
3342 	{
3343 		pyfsntfs_error_raise(
3344 		 error,
3345 		 PyExc_IOError,
3346 		 "%s: unable to retrieve security descriptor data.",
3347 		 function );
3348 
3349 		libcerror_error_free(
3350 		 &error );
3351 
3352 		Py_DecRef(
3353 		 (PyObject *) string_object );
3354 
3355 		return( NULL );
3356 	}
3357 	return( string_object );
3358 }
3359 
3360 /* Retrieves the number of attributes
3361  * Returns a Python object if successful or NULL on error
3362  */
pyfsntfs_file_entry_get_number_of_attributes(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)3363 PyObject *pyfsntfs_file_entry_get_number_of_attributes(
3364            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3365            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
3366 {
3367 	libcerror_error_t *error = NULL;
3368 	PyObject *integer_object = NULL;
3369 	static char *function    = "pyfsntfs_file_entry_get_number_of_attributes";
3370 	int number_of_attributes = 0;
3371 	int result               = 0;
3372 
3373 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
3374 
3375 	if( pyfsntfs_file_entry == NULL )
3376 	{
3377 		PyErr_Format(
3378 		 PyExc_ValueError,
3379 		 "%s: invalid file entry.",
3380 		 function );
3381 
3382 		return( NULL );
3383 	}
3384 	Py_BEGIN_ALLOW_THREADS
3385 
3386 	result = libfsntfs_file_entry_get_number_of_attributes(
3387 	          pyfsntfs_file_entry->file_entry,
3388 	          &number_of_attributes,
3389 	          &error );
3390 
3391 	Py_END_ALLOW_THREADS
3392 
3393 	if( result != 1 )
3394 	{
3395 		pyfsntfs_error_raise(
3396 		 error,
3397 		 PyExc_IOError,
3398 		 "%s: unable to retrieve number of attributes.",
3399 		 function );
3400 
3401 		libcerror_error_free(
3402 		 &error );
3403 
3404 		return( NULL );
3405 	}
3406 #if PY_MAJOR_VERSION >= 3
3407 	integer_object = PyLong_FromLong(
3408 	                  (long) number_of_attributes );
3409 #else
3410 	integer_object = PyInt_FromLong(
3411 	                  (long) number_of_attributes );
3412 #endif
3413 	return( integer_object );
3414 }
3415 
3416 /* Retrieves a specific attribute by index
3417  * Returns a Python object if successful or NULL on error
3418  */
pyfsntfs_file_entry_get_attribute_by_index(PyObject * pyfsntfs_file_entry,int attribute_index)3419 PyObject *pyfsntfs_file_entry_get_attribute_by_index(
3420            PyObject *pyfsntfs_file_entry,
3421            int attribute_index )
3422 {
3423 	libcerror_error_t *error         = NULL;
3424 	libfsntfs_attribute_t *attribute = NULL;
3425 	PyObject *attribute_object       = NULL;
3426 	PyTypeObject *type_object        = NULL;
3427 	static char *function            = "pyfsntfs_file_entry_get_attribute_by_index";
3428 	uint32_t attribute_type          = 0;
3429 	int result                       = 0;
3430 
3431 	if( pyfsntfs_file_entry == NULL )
3432 	{
3433 		PyErr_Format(
3434 		 PyExc_ValueError,
3435 		 "%s: invalid file entry.",
3436 		 function );
3437 
3438 		return( NULL );
3439 	}
3440 	Py_BEGIN_ALLOW_THREADS
3441 
3442 	result = libfsntfs_file_entry_get_attribute_by_index(
3443 	          ( (pyfsntfs_file_entry_t *) pyfsntfs_file_entry )->file_entry,
3444 	          attribute_index,
3445 	          &attribute,
3446 	          &error );
3447 
3448 	Py_END_ALLOW_THREADS
3449 
3450 	if( result != 1 )
3451 	{
3452 		pyfsntfs_error_raise(
3453 		 error,
3454 		 PyExc_IOError,
3455 		 "%s: unable to retrieve attribute: %d.",
3456 		 function,
3457 		 attribute_index );
3458 
3459 		libcerror_error_free(
3460 		 &error );
3461 
3462 		goto on_error;
3463 	}
3464 	Py_BEGIN_ALLOW_THREADS
3465 
3466 	result = libfsntfs_attribute_get_type(
3467 	          attribute,
3468 	          &attribute_type,
3469 	          &error );
3470 
3471 	Py_END_ALLOW_THREADS
3472 
3473 	if( result != 1 )
3474 	{
3475 		pyfsntfs_error_raise(
3476 		 error,
3477 		 PyExc_IOError,
3478 		 "%s: unable to retrieve type.",
3479 		 function );
3480 
3481 		libcerror_error_free(
3482 		 &error );
3483 
3484 		return( NULL );
3485 	}
3486 	switch( attribute_type )
3487 	{
3488 		case LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME:
3489 			type_object = &pyfsntfs_file_name_attribute_type_object;
3490 			break;
3491 
3492 		case LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER:
3493 			type_object = &pyfsntfs_object_identifier_attribute_type_object;
3494 			break;
3495 
3496 		case LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT:
3497 			type_object = &pyfsntfs_reparse_point_attribute_type_object;
3498 			break;
3499 
3500 		case LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR:
3501 			type_object = &pyfsntfs_security_descriptor_attribute_type_object;
3502 			break;
3503 
3504 		case LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION:
3505 			type_object = &pyfsntfs_standard_information_attribute_type_object;
3506 			break;
3507 
3508 		case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION:
3509 			type_object = &pyfsntfs_volume_information_attribute_type_object;
3510 			break;
3511 
3512 		case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME:
3513 			type_object = &pyfsntfs_volume_name_attribute_type_object;
3514 			break;
3515 
3516 		default:
3517 			type_object = &pyfsntfs_attribute_type_object;
3518 			break;
3519 	}
3520 	attribute_object = pyfsntfs_attribute_new(
3521 	                    type_object,
3522 	                    attribute,
3523 	                    pyfsntfs_file_entry );
3524 
3525 	if( attribute_object == NULL )
3526 	{
3527 		PyErr_Format(
3528 		 PyExc_MemoryError,
3529 		 "%s: unable to create attribute object.",
3530 		 function );
3531 
3532 		goto on_error;
3533 	}
3534 	return( attribute_object );
3535 
3536 on_error:
3537 	if( attribute != NULL )
3538 	{
3539 		libfsntfs_attribute_free(
3540 		 &attribute,
3541 		 NULL );
3542 	}
3543 	return( NULL );
3544 }
3545 
3546 /* Retrieves a specific attribute
3547  * Returns a Python object if successful or NULL on error
3548  */
pyfsntfs_file_entry_get_attribute(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)3549 PyObject *pyfsntfs_file_entry_get_attribute(
3550            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3551            PyObject *arguments,
3552            PyObject *keywords )
3553 {
3554 	PyObject *attribute_object  = NULL;
3555 	static char *keyword_list[] = { "attribute_index", NULL };
3556 	int attribute_index         = 0;
3557 
3558 	if( PyArg_ParseTupleAndKeywords(
3559 	     arguments,
3560 	     keywords,
3561 	     "i",
3562 	     keyword_list,
3563 	     &attribute_index ) == 0 )
3564 	{
3565 		return( NULL );
3566 	}
3567 	attribute_object = pyfsntfs_file_entry_get_attribute_by_index(
3568 	                    (PyObject *) pyfsntfs_file_entry,
3569 	                    attribute_index );
3570 
3571 	return( attribute_object );
3572 }
3573 
3574 /* Retrieves an attributes sequence and iterator object for the attributes
3575  * Returns a Python object if successful or NULL on error
3576  */
pyfsntfs_file_entry_get_attributes(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)3577 PyObject *pyfsntfs_file_entry_get_attributes(
3578            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3579            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
3580 {
3581 	libcerror_error_t *error    = NULL;
3582 	PyObject *attributes_object = NULL;
3583 	static char *function       = "pyfsntfs_file_entry_get_attributes";
3584 	int number_of_attributes    = 0;
3585 	int result                  = 0;
3586 
3587 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
3588 
3589 	if( pyfsntfs_file_entry == NULL )
3590 	{
3591 		PyErr_Format(
3592 		 PyExc_ValueError,
3593 		 "%s: invalid file entry.",
3594 		 function );
3595 
3596 		return( NULL );
3597 	}
3598 	Py_BEGIN_ALLOW_THREADS
3599 
3600 	result = libfsntfs_file_entry_get_number_of_attributes(
3601 	          pyfsntfs_file_entry->file_entry,
3602 	          &number_of_attributes,
3603 	          &error );
3604 
3605 	Py_END_ALLOW_THREADS
3606 
3607 	if( result != 1 )
3608 	{
3609 		pyfsntfs_error_raise(
3610 		 error,
3611 		 PyExc_IOError,
3612 		 "%s: unable to retrieve number of attributes.",
3613 		 function );
3614 
3615 		libcerror_error_free(
3616 		 &error );
3617 
3618 		return( NULL );
3619 	}
3620 	attributes_object = pyfsntfs_attributes_new(
3621 	                     (PyObject *) pyfsntfs_file_entry,
3622 	                     &pyfsntfs_file_entry_get_attribute_by_index,
3623 	                     number_of_attributes );
3624 
3625 	if( attributes_object == NULL )
3626 	{
3627 		PyErr_Format(
3628 		 PyExc_MemoryError,
3629 		 "%s: unable to create attributes object.",
3630 		 function );
3631 
3632 		return( NULL );
3633 	}
3634 	return( attributes_object );
3635 }
3636 
3637 /* Retrieves the number of alternate data streams
3638  * Returns a Python object if successful or NULL on error
3639  */
pyfsntfs_file_entry_get_number_of_alternate_data_streams(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)3640 PyObject *pyfsntfs_file_entry_get_number_of_alternate_data_streams(
3641            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3642            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
3643 {
3644 	libcerror_error_t *error             = NULL;
3645 	PyObject *integer_object             = NULL;
3646 	static char *function                = "pyfsntfs_file_entry_get_number_of_alternate_data_streams";
3647 	int number_of_alternate_data_streams = 0;
3648 	int result                           = 0;
3649 
3650 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
3651 
3652 	if( pyfsntfs_file_entry == NULL )
3653 	{
3654 		PyErr_Format(
3655 		 PyExc_ValueError,
3656 		 "%s: invalid file entry.",
3657 		 function );
3658 
3659 		return( NULL );
3660 	}
3661 	Py_BEGIN_ALLOW_THREADS
3662 
3663 	result = libfsntfs_file_entry_get_number_of_alternate_data_streams(
3664 	          pyfsntfs_file_entry->file_entry,
3665 	          &number_of_alternate_data_streams,
3666 	          &error );
3667 
3668 	Py_END_ALLOW_THREADS
3669 
3670 	if( result != 1 )
3671 	{
3672 		pyfsntfs_error_raise(
3673 		 error,
3674 		 PyExc_IOError,
3675 		 "%s: unable to retrieve number of alternate data streams.",
3676 		 function );
3677 
3678 		libcerror_error_free(
3679 		 &error );
3680 
3681 		return( NULL );
3682 	}
3683 #if PY_MAJOR_VERSION >= 3
3684 	integer_object = PyLong_FromLong(
3685 	                  (long) number_of_alternate_data_streams );
3686 #else
3687 	integer_object = PyInt_FromLong(
3688 	                  (long) number_of_alternate_data_streams );
3689 #endif
3690 	return( integer_object );
3691 }
3692 
3693 /* Retrieves a specific alternate data stream by index
3694  * Returns a Python object if successful or NULL on error
3695  */
pyfsntfs_file_entry_get_alternate_data_stream_by_index(PyObject * pyfsntfs_file_entry,int alternate_data_stream_index)3696 PyObject *pyfsntfs_file_entry_get_alternate_data_stream_by_index(
3697            PyObject *pyfsntfs_file_entry,
3698            int alternate_data_stream_index )
3699 {
3700 	libcerror_error_t *error             = NULL;
3701 	libfsntfs_data_stream_t *data_stream = NULL;
3702 	PyObject *data_stream_object         = NULL;
3703 	static char *function                = "pyfsntfs_file_entry_get_alternate_data_stream_by_index";
3704 	int result                           = 0;
3705 
3706 	if( pyfsntfs_file_entry == NULL )
3707 	{
3708 		PyErr_Format(
3709 		 PyExc_ValueError,
3710 		 "%s: invalid file entry.",
3711 		 function );
3712 
3713 		return( NULL );
3714 	}
3715 	Py_BEGIN_ALLOW_THREADS
3716 
3717 	result = libfsntfs_file_entry_get_alternate_data_stream_by_index(
3718 	          ( (pyfsntfs_file_entry_t *) pyfsntfs_file_entry )->file_entry,
3719 	          alternate_data_stream_index,
3720 	          &data_stream,
3721 	          &error );
3722 
3723 	Py_END_ALLOW_THREADS
3724 
3725 	if( result != 1 )
3726 	{
3727 		pyfsntfs_error_raise(
3728 		 error,
3729 		 PyExc_IOError,
3730 		 "%s: unable to retrieve alternate data stream: %d.",
3731 		 function,
3732 		 alternate_data_stream_index );
3733 
3734 		libcerror_error_free(
3735 		 &error );
3736 
3737 		goto on_error;
3738 	}
3739 	data_stream_object = pyfsntfs_data_stream_new(
3740 	                      data_stream,
3741 	                      pyfsntfs_file_entry );
3742 
3743 	if( data_stream_object == NULL )
3744 	{
3745 		PyErr_Format(
3746 		 PyExc_MemoryError,
3747 		 "%s: unable to create alternate data stream object.",
3748 		 function );
3749 
3750 		goto on_error;
3751 	}
3752 	return( data_stream_object );
3753 
3754 on_error:
3755 	if( data_stream != NULL )
3756 	{
3757 		libfsntfs_data_stream_free(
3758 		 &data_stream,
3759 		 NULL );
3760 	}
3761 	return( NULL );
3762 }
3763 
3764 /* Retrieves a specific alternate data stream
3765  * Returns a Python object if successful or NULL on error
3766  */
pyfsntfs_file_entry_get_alternate_data_stream(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)3767 PyObject *pyfsntfs_file_entry_get_alternate_data_stream(
3768            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3769            PyObject *arguments,
3770            PyObject *keywords )
3771 {
3772 	PyObject *data_stream_object    = NULL;
3773 	static char *keyword_list[]     = { "alternate_data_stream_index", NULL };
3774 	int alternate_data_stream_index = 0;
3775 
3776 	if( PyArg_ParseTupleAndKeywords(
3777 	     arguments,
3778 	     keywords,
3779 	     "i",
3780 	     keyword_list,
3781 	     &alternate_data_stream_index ) == 0 )
3782 	{
3783 		return( NULL );
3784 	}
3785 	data_stream_object = pyfsntfs_file_entry_get_alternate_data_stream_by_index(
3786 	                      (PyObject *) pyfsntfs_file_entry,
3787 	                      alternate_data_stream_index );
3788 
3789 	return( data_stream_object );
3790 }
3791 
3792 /* Retrieves a data streams sequence and iterator object for the alternate data streams
3793  * Returns a Python object if successful or NULL on error
3794  */
pyfsntfs_file_entry_get_alternate_data_streams(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)3795 PyObject *pyfsntfs_file_entry_get_alternate_data_streams(
3796            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3797            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
3798 {
3799 	libcerror_error_t *error             = NULL;
3800 	PyObject *data_streams_object        = NULL;
3801 	static char *function                = "pyfsntfs_file_entry_get_alternate_data_streams";
3802 	int number_of_alternate_data_streams = 0;
3803 	int result                           = 0;
3804 
3805 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
3806 
3807 	if( pyfsntfs_file_entry == NULL )
3808 	{
3809 		PyErr_Format(
3810 		 PyExc_ValueError,
3811 		 "%s: invalid file entry.",
3812 		 function );
3813 
3814 		return( NULL );
3815 	}
3816 	Py_BEGIN_ALLOW_THREADS
3817 
3818 	result = libfsntfs_file_entry_get_number_of_alternate_data_streams(
3819 	          pyfsntfs_file_entry->file_entry,
3820 	          &number_of_alternate_data_streams,
3821 	          &error );
3822 
3823 	Py_END_ALLOW_THREADS
3824 
3825 	if( result != 1 )
3826 	{
3827 		pyfsntfs_error_raise(
3828 		 error,
3829 		 PyExc_IOError,
3830 		 "%s: unable to retrieve number of alternate data streams.",
3831 		 function );
3832 
3833 		libcerror_error_free(
3834 		 &error );
3835 
3836 		return( NULL );
3837 	}
3838 	data_streams_object = pyfsntfs_data_streams_new(
3839 	                       (PyObject *) pyfsntfs_file_entry,
3840 	                       &pyfsntfs_file_entry_get_alternate_data_stream_by_index,
3841 	                       number_of_alternate_data_streams );
3842 
3843 	if( data_streams_object == NULL )
3844 	{
3845 		PyErr_Format(
3846 		 PyExc_MemoryError,
3847 		 "%s: unable to create data streams object.",
3848 		 function );
3849 
3850 		return( NULL );
3851 	}
3852 	return( data_streams_object );
3853 }
3854 
3855 /* Determines if there is an alternate data stream specified by the name
3856  * Returns a Python object if successful or NULL on error
3857  */
pyfsntfs_file_entry_has_alternate_data_stream_by_name(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)3858 PyObject *pyfsntfs_file_entry_has_alternate_data_stream_by_name(
3859            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3860            PyObject *arguments,
3861            PyObject *keywords )
3862 {
3863 	libcerror_error_t *error       = NULL;
3864 	char *data_stream_name         = NULL;
3865 	static char *keyword_list[]    = { "data_stream_name", NULL };
3866 	static char *function          = "pyfsntfs_file_entry_has_alternate_data_stream_by_name";
3867 	size_t data_stream_name_length = 0;
3868 	int result                     = 0;
3869 
3870 	if( pyfsntfs_file_entry == NULL )
3871 	{
3872 		PyErr_Format(
3873 		 PyExc_ValueError,
3874 		 "%s: invalid file entry.",
3875 		 function );
3876 
3877 		return( NULL );
3878 	}
3879 	if( PyArg_ParseTupleAndKeywords(
3880 	     arguments,
3881 	     keywords,
3882 	     "s",
3883 	     keyword_list,
3884 	     &data_stream_name ) == 0 )
3885 	{
3886 		return( NULL );
3887 	}
3888 	data_stream_name_length = narrow_string_length(
3889 	                           data_stream_name );
3890 
3891 	Py_BEGIN_ALLOW_THREADS
3892 
3893 	result = libfsntfs_file_entry_has_alternate_data_stream_by_utf8_name(
3894 	           pyfsntfs_file_entry->file_entry,
3895 	           (uint8_t *) data_stream_name,
3896 	           data_stream_name_length,
3897 	           &error );
3898 
3899 	Py_END_ALLOW_THREADS
3900 
3901 	if( result == -1 )
3902 	{
3903 		pyfsntfs_error_raise(
3904 		 error,
3905 		 PyExc_IOError,
3906 		 "%s: unable to determine if alternate data stream exists.",
3907 		 function );
3908 
3909 		libcerror_error_free(
3910 		 &error );
3911 
3912 		return( NULL );
3913 	}
3914 	/* Check if the alternate data stream is present
3915 	 */
3916 	if( result != 0 )
3917 	{
3918 		Py_IncRef(
3919 		 (PyObject *) Py_True );
3920 
3921 		return( Py_True );
3922 	}
3923 	Py_IncRef(
3924 	 (PyObject *) Py_False );
3925 
3926 	return( Py_False );
3927 }
3928 
3929 /* Retrieves the alternate data stream specified by the name
3930  * Returns a Python object if successful or NULL on error
3931  */
pyfsntfs_file_entry_get_alternate_data_stream_by_name(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)3932 PyObject *pyfsntfs_file_entry_get_alternate_data_stream_by_name(
3933            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
3934            PyObject *arguments,
3935            PyObject *keywords )
3936 {
3937 	libcerror_error_t *error             = NULL;
3938 	libfsntfs_data_stream_t *data_stream = NULL;
3939 	PyObject *data_stream_object         = NULL;
3940 	char *data_stream_name               = NULL;
3941 	static char *keyword_list[]          = { "data_stream_name", NULL };
3942 	static char *function                = "pyfsntfs_file_entry_get_alternate_data_stream_by_name";
3943 	size_t data_stream_name_length       = 0;
3944 	int result                           = 0;
3945 
3946 	if( pyfsntfs_file_entry == NULL )
3947 	{
3948 		PyErr_Format(
3949 		 PyExc_ValueError,
3950 		 "%s: invalid file entry.",
3951 		 function );
3952 
3953 		return( NULL );
3954 	}
3955 	if( PyArg_ParseTupleAndKeywords(
3956 	     arguments,
3957 	     keywords,
3958 	     "s",
3959 	     keyword_list,
3960 	     &data_stream_name ) == 0 )
3961 	{
3962 		goto on_error;
3963 	}
3964 	data_stream_name_length = narrow_string_length(
3965 	                           data_stream_name );
3966 
3967 	Py_BEGIN_ALLOW_THREADS
3968 
3969 	result = libfsntfs_file_entry_get_alternate_data_stream_by_utf8_name(
3970 	           pyfsntfs_file_entry->file_entry,
3971 	           (uint8_t *) data_stream_name,
3972 	           data_stream_name_length,
3973 	           &data_stream,
3974 	           &error );
3975 
3976 	Py_END_ALLOW_THREADS
3977 
3978 	if( result == -1 )
3979 	{
3980 		pyfsntfs_error_raise(
3981 		 error,
3982 		 PyExc_IOError,
3983 		 "%s: unable to retrieve alternate data stream.",
3984 		 function );
3985 
3986 		libcerror_error_free(
3987 		 &error );
3988 
3989 		goto on_error;
3990 	}
3991 	/* Check if the alternate data stream is present
3992 	 */
3993 	else if( result == 0 )
3994 	{
3995 		Py_IncRef(
3996 		 Py_None );
3997 
3998 		return( Py_None );
3999 	}
4000 	data_stream_object = pyfsntfs_data_stream_new(
4001 	                      data_stream,
4002 	                      (PyObject *) pyfsntfs_file_entry );
4003 
4004 	if( data_stream_object == NULL )
4005 	{
4006 		PyErr_Format(
4007 		 PyExc_MemoryError,
4008 		 "%s: unable to create data stream object.",
4009 		 function );
4010 
4011 		goto on_error;
4012 	}
4013 	return( data_stream_object );
4014 
4015 on_error:
4016 	if( data_stream != NULL )
4017 	{
4018 		libfsntfs_data_stream_free(
4019 		 &data_stream,
4020 		 NULL );
4021 	}
4022 	return( NULL );
4023 }
4024 
4025 /* Retrieves the number of sub file entries
4026  * Returns a Python object if successful or NULL on error
4027  */
pyfsntfs_file_entry_get_number_of_sub_file_entries(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)4028 PyObject *pyfsntfs_file_entry_get_number_of_sub_file_entries(
4029            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
4030            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
4031 {
4032 	libcerror_error_t *error       = NULL;
4033 	PyObject *integer_object       = NULL;
4034 	static char *function          = "pyfsntfs_file_entry_get_number_of_sub_file_entries";
4035 	int number_of_sub_file_entries = 0;
4036 	int result                     = 0;
4037 
4038 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
4039 
4040 	if( pyfsntfs_file_entry == NULL )
4041 	{
4042 		PyErr_Format(
4043 		 PyExc_ValueError,
4044 		 "%s: invalid file entry.",
4045 		 function );
4046 
4047 		return( NULL );
4048 	}
4049 	Py_BEGIN_ALLOW_THREADS
4050 
4051 	result = libfsntfs_file_entry_get_number_of_sub_file_entries(
4052 	          pyfsntfs_file_entry->file_entry,
4053 	          &number_of_sub_file_entries,
4054 	          &error );
4055 
4056 	Py_END_ALLOW_THREADS
4057 
4058 	if( result != 1 )
4059 	{
4060 		pyfsntfs_error_raise(
4061 		 error,
4062 		 PyExc_IOError,
4063 		 "%s: unable to retrieve number of sub file entries.",
4064 		 function );
4065 
4066 		libcerror_error_free(
4067 		 &error );
4068 
4069 		return( NULL );
4070 	}
4071 #if PY_MAJOR_VERSION >= 3
4072 	integer_object = PyLong_FromLong(
4073 	                  (long) number_of_sub_file_entries );
4074 #else
4075 	integer_object = PyInt_FromLong(
4076 	                  (long) number_of_sub_file_entries );
4077 #endif
4078 	return( integer_object );
4079 }
4080 
4081 /* Retrieves a specific sub file entry by index
4082  * Returns a Python object if successful or NULL on error
4083  */
pyfsntfs_file_entry_get_sub_file_entry_by_index(PyObject * pyfsntfs_file_entry,int sub_file_entry_index)4084 PyObject *pyfsntfs_file_entry_get_sub_file_entry_by_index(
4085            PyObject *pyfsntfs_file_entry,
4086            int sub_file_entry_index )
4087 {
4088 	libcerror_error_t *error               = NULL;
4089 	libfsntfs_file_entry_t *sub_file_entry = NULL;
4090 	PyObject *file_entry_object            = NULL;
4091 	static char *function                  = "pyfsntfs_file_entry_get_sub_file_entry_by_index";
4092 	int result                             = 0;
4093 
4094 	if( pyfsntfs_file_entry == NULL )
4095 	{
4096 		PyErr_Format(
4097 		 PyExc_ValueError,
4098 		 "%s: invalid file entry.",
4099 		 function );
4100 
4101 		return( NULL );
4102 	}
4103 	Py_BEGIN_ALLOW_THREADS
4104 
4105 	result = libfsntfs_file_entry_get_sub_file_entry_by_index(
4106 	          ( (pyfsntfs_file_entry_t *) pyfsntfs_file_entry )->file_entry,
4107 	          sub_file_entry_index,
4108 	          &sub_file_entry,
4109 	          &error );
4110 
4111 	Py_END_ALLOW_THREADS
4112 
4113 	if( result != 1 )
4114 	{
4115 		pyfsntfs_error_raise(
4116 		 error,
4117 		 PyExc_IOError,
4118 		 "%s: unable to retrieve sub file entry: %d.",
4119 		 function,
4120 		 sub_file_entry_index );
4121 
4122 		libcerror_error_free(
4123 		 &error );
4124 
4125 		goto on_error;
4126 	}
4127 	file_entry_object = pyfsntfs_file_entry_new(
4128 	                     sub_file_entry,
4129 	                     ( (pyfsntfs_file_entry_t *) pyfsntfs_file_entry )->parent_object );
4130 
4131 	if( file_entry_object == NULL )
4132 	{
4133 		PyErr_Format(
4134 		 PyExc_MemoryError,
4135 		 "%s: unable to create file entry object.",
4136 		 function );
4137 
4138 		goto on_error;
4139 	}
4140 	return( file_entry_object );
4141 
4142 on_error:
4143 	if( sub_file_entry != NULL )
4144 	{
4145 		libfsntfs_file_entry_free(
4146 		 &sub_file_entry,
4147 		 NULL );
4148 	}
4149 	return( NULL );
4150 }
4151 
4152 /* Retrieves a specific sub file entry
4153  * Returns a Python object if successful or NULL on error
4154  */
pyfsntfs_file_entry_get_sub_file_entry(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments,PyObject * keywords)4155 PyObject *pyfsntfs_file_entry_get_sub_file_entry(
4156            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
4157            PyObject *arguments,
4158            PyObject *keywords )
4159 {
4160 	PyObject *file_entry_object = NULL;
4161 	static char *keyword_list[] = { "sub_file_entry_index", NULL };
4162 	int sub_file_entry_index    = 0;
4163 
4164 	if( PyArg_ParseTupleAndKeywords(
4165 	     arguments,
4166 	     keywords,
4167 	     "i",
4168 	     keyword_list,
4169 	     &sub_file_entry_index ) == 0 )
4170 	{
4171 		return( NULL );
4172 	}
4173 	file_entry_object = pyfsntfs_file_entry_get_sub_file_entry_by_index(
4174 	                     (PyObject *) pyfsntfs_file_entry,
4175 	                     sub_file_entry_index );
4176 
4177 	return( file_entry_object );
4178 }
4179 
4180 /* Retrieves a file entries sequence and iterator object for the sub file entries
4181  * Returns a Python object if successful or NULL on error
4182  */
pyfsntfs_file_entry_get_sub_file_entries(pyfsntfs_file_entry_t * pyfsntfs_file_entry,PyObject * arguments PYFSNTFS_ATTRIBUTE_UNUSED)4183 PyObject *pyfsntfs_file_entry_get_sub_file_entries(
4184            pyfsntfs_file_entry_t *pyfsntfs_file_entry,
4185            PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED )
4186 {
4187 	libcerror_error_t *error       = NULL;
4188 	PyObject *file_entries_object  = NULL;
4189 	static char *function          = "pyfsntfs_file_entry_get_sub_file_entries";
4190 	int number_of_sub_file_entries = 0;
4191 	int result                     = 0;
4192 
4193 	PYFSNTFS_UNREFERENCED_PARAMETER( arguments )
4194 
4195 	if( pyfsntfs_file_entry == NULL )
4196 	{
4197 		PyErr_Format(
4198 		 PyExc_ValueError,
4199 		 "%s: invalid file entry.",
4200 		 function );
4201 
4202 		return( NULL );
4203 	}
4204 	Py_BEGIN_ALLOW_THREADS
4205 
4206 	result = libfsntfs_file_entry_get_number_of_sub_file_entries(
4207 	          pyfsntfs_file_entry->file_entry,
4208 	          &number_of_sub_file_entries,
4209 	          &error );
4210 
4211 	Py_END_ALLOW_THREADS
4212 
4213 	if( result != 1 )
4214 	{
4215 		pyfsntfs_error_raise(
4216 		 error,
4217 		 PyExc_IOError,
4218 		 "%s: unable to retrieve number of sub file entries.",
4219 		 function );
4220 
4221 		libcerror_error_free(
4222 		 &error );
4223 
4224 		return( NULL );
4225 	}
4226 	file_entries_object = pyfsntfs_file_entries_new(
4227 	                       (PyObject *) pyfsntfs_file_entry,
4228 	                       &pyfsntfs_file_entry_get_sub_file_entry_by_index,
4229 	                       number_of_sub_file_entries );
4230 
4231 	if( file_entries_object == NULL )
4232 	{
4233 		PyErr_Format(
4234 		 PyExc_MemoryError,
4235 		 "%s: unable to create file entries object.",
4236 		 function );
4237 
4238 		return( NULL );
4239 	}
4240 	return( file_entries_object );
4241 }
4242 
4243