1 /*
2  * Python object wrapper of libfsapfs_file_entry_t
3  *
4  * Copyright (C) 2018-2021, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <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 "pyfsapfs_datetime.h"
31 #include "pyfsapfs_error.h"
32 #include "pyfsapfs_extended_attribute.h"
33 #include "pyfsapfs_extended_attributes.h"
34 #include "pyfsapfs_file_entries.h"
35 #include "pyfsapfs_file_entry.h"
36 #include "pyfsapfs_integer.h"
37 #include "pyfsapfs_libcerror.h"
38 #include "pyfsapfs_libfsapfs.h"
39 #include "pyfsapfs_python.h"
40 #include "pyfsapfs_unused.h"
41 
42 PyMethodDef pyfsapfs_file_entry_object_methods[] = {
43 
44 	{ "get_identifier",
45 	  (PyCFunction) pyfsapfs_file_entry_get_identifier,
46 	  METH_NOARGS,
47 	  "get_identifier() -> Integer\n"
48 	  "\n"
49 	  "Retrieves the identifier." },
50 
51 	{ "get_parent_identifier",
52 	  (PyCFunction) pyfsapfs_file_entry_get_parent_identifier,
53 	  METH_NOARGS,
54 	  "get_parent_identifier() -> Integer\n"
55 	  "\n"
56 	  "Retrieves the parent identifier." },
57 
58 	{ "get_creation_time",
59 	  (PyCFunction) pyfsapfs_file_entry_get_creation_time,
60 	  METH_NOARGS,
61 	  "get_creation_time() -> Datetime or None\n"
62 	  "\n"
63 	  "Returns the creation date and time." },
64 
65 	{ "get_creation_time_as_integer",
66 	  (PyCFunction) pyfsapfs_file_entry_get_creation_time_as_integer,
67 	  METH_NOARGS,
68 	  "get_creation_time_as_integer() -> Integer or None\n"
69 	  "\n"
70 	  "Returns the creation date and time as a 64-bit integer containing an APFS timestamp value." },
71 
72 	{ "get_modification_time",
73 	  (PyCFunction) pyfsapfs_file_entry_get_modification_time,
74 	  METH_NOARGS,
75 	  "get_modification_time() -> Datetime or None\n"
76 	  "\n"
77 	  "Returns the modification date and time." },
78 
79 	{ "get_modification_time_as_integer",
80 	  (PyCFunction) pyfsapfs_file_entry_get_modification_time_as_integer,
81 	  METH_NOARGS,
82 	  "get_modification_time_as_integer() -> Integer or None\n"
83 	  "\n"
84 	  "Returns the modification date and time as a 64-bit integer containing an APFS timestamp value." },
85 
86 	{ "get_access_time",
87 	  (PyCFunction) pyfsapfs_file_entry_get_access_time,
88 	  METH_NOARGS,
89 	  "get_access_time() -> Datetime or None\n"
90 	  "\n"
91 	  "Returns the access date and time." },
92 
93 	{ "get_access_time_as_integer",
94 	  (PyCFunction) pyfsapfs_file_entry_get_access_time_as_integer,
95 	  METH_NOARGS,
96 	  "get_access_time_as_integer() -> Integer or None\n"
97 	  "\n"
98 	  "Returns the access date and time as a 64-bit integer containing an APFS timestamp value." },
99 
100 	{ "get_inode_change_time",
101 	  (PyCFunction) pyfsapfs_file_entry_get_inode_change_time,
102 	  METH_NOARGS,
103 	  "get_inode_change_time() -> Datetime or None\n"
104 	  "\n"
105 	  "Returns the inode change date and time." },
106 
107 	{ "get_inode_change_time_as_integer",
108 	  (PyCFunction) pyfsapfs_file_entry_get_inode_change_time_as_integer,
109 	  METH_NOARGS,
110 	  "get_inode_change_time_as_integer() -> Integer or None\n"
111 	  "\n"
112 	  "Returns the inode change date and time as a 64-bit integer containing an APFS timestamp value." },
113 
114 	{ "get_added_time",
115 	  (PyCFunction) pyfsapfs_file_entry_get_added_time,
116 	  METH_NOARGS,
117 	  "get_added_time() -> Datetime or None\n"
118 	  "\n"
119 	  "Returns the added date and time." },
120 
121 	{ "get_added_time_as_integer",
122 	  (PyCFunction) pyfsapfs_file_entry_get_added_time_as_integer,
123 	  METH_NOARGS,
124 	  "get_added_time_as_integer() -> Integer or None\n"
125 	  "\n"
126 	  "Returns the added date and time as a 64-bit integer containing an APFS timestamp value." },
127 
128 	{ "get_owner_identifier",
129 	  (PyCFunction) pyfsapfs_file_entry_get_owner_identifier,
130 	  METH_NOARGS,
131 	  "get_owner_identifier() -> Integer\n"
132 	  "\n"
133 	  "Retrieves the owner identifier." },
134 
135 	{ "get_group_identifier",
136 	  (PyCFunction) pyfsapfs_file_entry_get_group_identifier,
137 	  METH_NOARGS,
138 	  "get_group_identifier() -> Integer\n"
139 	  "\n"
140 	  "Retrieves the group identifier." },
141 
142 	{ "get_file_mode",
143 	  (PyCFunction) pyfsapfs_file_entry_get_file_mode,
144 	  METH_NOARGS,
145 	  "get_file_mode() -> Integer\n"
146 	  "\n"
147 	  "Retrieves the file mode." },
148 
149 	{ "get_name",
150 	  (PyCFunction) pyfsapfs_file_entry_get_name,
151 	  METH_NOARGS,
152 	  "get_name() -> Unicode string\n"
153 	  "\n"
154 	  "Retrieves the name." },
155 
156 	{ "get_symbolic_link_target",
157 	  (PyCFunction) pyfsapfs_file_entry_get_symbolic_link_target,
158 	  METH_NOARGS,
159 	  "get_symbolic_link_target() -> Unicode string or None\n"
160 	  "\n"
161 	  "Returns the symbolic link target." },
162 
163 	{ "get_number_of_extended_attributes",
164 	  (PyCFunction) pyfsapfs_file_entry_get_number_of_extended_attributes,
165 	  METH_NOARGS,
166 	  "get_number_of_extended_attributes() -> Integer\n"
167 	  "\n"
168 	  "Retrieves the number of extended attributes." },
169 
170 	{ "get_extended_attribute",
171 	  (PyCFunction) pyfsapfs_file_entry_get_extended_attribute,
172 	  METH_VARARGS | METH_KEYWORDS,
173 	  "get_extended_attribute(extended_attribute_index) -> Object\n"
174 	  "\n"
175 	  "Retrieves the extended attribute specified by the index." },
176 
177 	{ "has_extended_attribute_by_name",
178 	  (PyCFunction) pyfsapfs_file_entry_has_extended_attribute_by_name,
179 	  METH_VARARGS | METH_KEYWORDS,
180 	  "has_extended_attribute_by_name(name) -> Boolean\n"
181 	  "\n"
182 	  "Determines if there is an extended attribute specified by the name." },
183 
184 	{ "get_extended_attribute_by_name",
185 	  (PyCFunction) pyfsapfs_file_entry_get_extended_attribute_by_name,
186 	  METH_VARARGS | METH_KEYWORDS,
187 	  "get_extended_attribute_by_name(name) -> Object or None\n"
188 	  "\n"
189 	  "Retrieves an extended attribute specified by the name." },
190 
191 	{ "get_number_of_sub_file_entries",
192 	  (PyCFunction) pyfsapfs_file_entry_get_number_of_sub_file_entries,
193 	  METH_NOARGS,
194 	  "get_number_of_sub_file_entries() -> Integer\n"
195 	  "\n"
196 	  "Retrieves the number of sub file entries." },
197 
198 	{ "get_sub_file_entry",
199 	  (PyCFunction) pyfsapfs_file_entry_get_sub_file_entry,
200 	  METH_VARARGS | METH_KEYWORDS,
201 	  "get_sub_file_entry(sub_file_entry_index) -> Object\n"
202 	  "\n"
203 	  "Retrieves the sub file entry specified by the index." },
204 
205 	{ "get_sub_file_entry_by_name",
206 	  (PyCFunction) pyfsapfs_file_entry_get_sub_file_entry_by_name,
207 	  METH_VARARGS | METH_KEYWORDS,
208 	  "get_sub_file_entry_by_name(name) -> Object\n"
209 	  "\n"
210 	  "Retrieves the sub file entry specified by the name." },
211 
212 	{ "read_buffer",
213 	  (PyCFunction) pyfsapfs_file_entry_read_buffer,
214 	  METH_VARARGS | METH_KEYWORDS,
215 	  "read_buffer(size) -> Binary string\n"
216 	  "\n"
217 	  "Reads a buffer of data." },
218 
219 	{ "read_buffer_at_offset",
220 	  (PyCFunction) pyfsapfs_file_entry_read_buffer_at_offset,
221 	  METH_VARARGS | METH_KEYWORDS,
222 	  "read_buffer_at_offset(size, offset) -> Binary string\n"
223 	  "\n"
224 	  "Reads a buffer of data at a specific offset." },
225 
226 	{ "seek_offset",
227 	  (PyCFunction) pyfsapfs_file_entry_seek_offset,
228 	  METH_VARARGS | METH_KEYWORDS,
229 	  "seek_offset(offset, whence) -> None\n"
230 	  "\n"
231 	  "Seeks an offset within the data." },
232 
233 	{ "get_offset",
234 	  (PyCFunction) pyfsapfs_file_entry_get_offset,
235 	  METH_NOARGS,
236 	  "get_offset() -> Integer\n"
237 	  "\n"
238 	  "Retrieves the current offset within the data." },
239 
240 	{ "read",
241 	  (PyCFunction) pyfsapfs_file_entry_read_buffer,
242 	  METH_VARARGS | METH_KEYWORDS,
243 	  "read(size) -> Binary string\n"
244 	  "\n"
245 	  "Reads a buffer of data." },
246 
247 	{ "seek",
248 	  (PyCFunction) pyfsapfs_file_entry_seek_offset,
249 	  METH_VARARGS | METH_KEYWORDS,
250 	  "seek(offset, whence) -> None\n"
251 	  "\n"
252 	  "Seeks an offset within the data." },
253 
254 	{ "tell",
255 	  (PyCFunction) pyfsapfs_file_entry_get_offset,
256 	  METH_NOARGS,
257 	  "tell() -> Integer\n"
258 	  "\n"
259 	  "Retrieves the current offset within the data." },
260 
261 	{ "get_size",
262 	  (PyCFunction) pyfsapfs_file_entry_get_size,
263 	  METH_NOARGS,
264 	  "get_size() -> Integer\n"
265 	  "\n"
266 	  "Retrieves the size." },
267 
268 	{ "get_number_of_extents",
269 	  (PyCFunction) pyfsapfs_file_entry_get_number_of_extents,
270 	  METH_NOARGS,
271 	  "get_number_of_extents() -> Integer\n"
272 	  "\n"
273 	  "Retrieves the number of extents." },
274 
275 	{ "get_extent",
276 	  (PyCFunction) pyfsapfs_file_entry_get_extent,
277 	  METH_VARARGS | METH_KEYWORDS,
278 	  "get_extent(extent_index) -> Integer\n"
279 	  "\n"
280 	  "Retrieves the extent specified by the index." },
281 
282 	/* Sentinel */
283 	{ NULL, NULL, 0, NULL }
284 };
285 
286 PyGetSetDef pyfsapfs_file_entry_object_get_set_definitions[] = {
287 
288 	{ "identifier",
289 	  (getter) pyfsapfs_file_entry_get_identifier,
290 	  (setter) 0,
291 	  "The identifier.",
292 	  NULL },
293 
294 	{ "parent_identifier",
295 	  (getter) pyfsapfs_file_entry_get_parent_identifier,
296 	  (setter) 0,
297 	  "The parent identifier.",
298 	  NULL },
299 
300 	{ "creation_time",
301 	  (getter) pyfsapfs_file_entry_get_creation_time,
302 	  (setter) 0,
303 	  "The creation date and time.",
304 	  NULL },
305 
306 	{ "modification_time",
307 	  (getter) pyfsapfs_file_entry_get_modification_time,
308 	  (setter) 0,
309 	  "The modification date and time.",
310 	  NULL },
311 
312 	{ "access_time",
313 	  (getter) pyfsapfs_file_entry_get_access_time,
314 	  (setter) 0,
315 	  "The access date and time.",
316 	  NULL },
317 
318 	{ "inode_change_time",
319 	  (getter) pyfsapfs_file_entry_get_inode_change_time,
320 	  (setter) 0,
321 	  "The extent.",
322 	  NULL },
323 
324 	{ "added_time",
325 	  (getter) pyfsapfs_file_entry_get_added_time,
326 	  (setter) 0,
327 	  "The added date and time.",
328 	  NULL },
329 
330 	{ "owner_identifier",
331 	  (getter) pyfsapfs_file_entry_get_owner_identifier,
332 	  (setter) 0,
333 	  "The owner identifier.",
334 	  NULL },
335 
336 	{ "group_identifier",
337 	  (getter) pyfsapfs_file_entry_get_group_identifier,
338 	  (setter) 0,
339 	  "The group identifier.",
340 	  NULL },
341 
342 	{ "file_mode",
343 	  (getter) pyfsapfs_file_entry_get_file_mode,
344 	  (setter) 0,
345 	  "The file mode.",
346 	  NULL },
347 
348 	{ "name",
349 	  (getter) pyfsapfs_file_entry_get_name,
350 	  (setter) 0,
351 	  "The name.",
352 	  NULL },
353 
354 	{ "symbolic_link_target",
355 	  (getter) pyfsapfs_file_entry_get_symbolic_link_target,
356 	  (setter) 0,
357 	  "The symbolic link target.",
358 	  NULL },
359 
360 	{ "number_of_extended_attributes",
361 	  (getter) pyfsapfs_file_entry_get_number_of_extended_attributes,
362 	  (setter) 0,
363 	  "The number of extended attributes.",
364 	  NULL },
365 
366 	{ "extended_attributes",
367 	  (getter) pyfsapfs_file_entry_get_extended_attributes,
368 	  (setter) 0,
369 	  "The extended attributes.",
370 	  NULL },
371 
372 	{ "number_of_sub_file_entries",
373 	  (getter) pyfsapfs_file_entry_get_number_of_sub_file_entries,
374 	  (setter) 0,
375 	  "The number of sub file entries.",
376 	  NULL },
377 
378 	{ "sub_file_entries",
379 	  (getter) pyfsapfs_file_entry_get_sub_file_entries,
380 	  (setter) 0,
381 	  "The sub file entries.",
382 	  NULL },
383 
384 	{ "size",
385 	  (getter) pyfsapfs_file_entry_get_size,
386 	  (setter) 0,
387 	  "The size.",
388 	  NULL },
389 
390 	{ "number_of_extents",
391 	  (getter) pyfsapfs_file_entry_get_number_of_extents,
392 	  (setter) 0,
393 	  "The number of extents.",
394 	  NULL },
395 
396 	/* Sentinel */
397 	{ NULL, NULL, NULL, NULL, NULL }
398 };
399 
400 PyTypeObject pyfsapfs_file_entry_type_object = {
401 	PyVarObject_HEAD_INIT( NULL, 0 )
402 
403 	/* tp_name */
404 	"pyfsapfs.file_entry",
405 	/* tp_basicsize */
406 	sizeof( pyfsapfs_file_entry_t ),
407 	/* tp_itemsize */
408 	0,
409 	/* tp_dealloc */
410 	(destructor) pyfsapfs_file_entry_free,
411 	/* tp_print */
412 	0,
413 	/* tp_getattr */
414 	0,
415 	/* tp_setattr */
416 	0,
417 	/* tp_compare */
418 	0,
419 	/* tp_repr */
420 	0,
421 	/* tp_as_number */
422 	0,
423 	/* tp_as_sequence */
424 	0,
425 	/* tp_as_mapping */
426 	0,
427 	/* tp_hash */
428 	0,
429 	/* tp_call */
430 	0,
431 	/* tp_str */
432 	0,
433 	/* tp_getattro */
434 	0,
435 	/* tp_setattro */
436 	0,
437 	/* tp_as_buffer */
438 	0,
439 	/* tp_flags */
440 	Py_TPFLAGS_DEFAULT,
441 	/* tp_doc */
442 	"pyfsapfs file entry object (wraps libfsapfs_file_entry_t)",
443 	/* tp_traverse */
444 	0,
445 	/* tp_clear */
446 	0,
447 	/* tp_richcompare */
448 	0,
449 	/* tp_weaklistoffset */
450 	0,
451 	/* tp_iter */
452 	0,
453 	/* tp_iternext */
454 	0,
455 	/* tp_methods */
456 	pyfsapfs_file_entry_object_methods,
457 	/* tp_members */
458 	0,
459 	/* tp_getset */
460 	pyfsapfs_file_entry_object_get_set_definitions,
461 	/* tp_base */
462 	0,
463 	/* tp_dict */
464 	0,
465 	/* tp_descr_get */
466 	0,
467 	/* tp_descr_set */
468 	0,
469 	/* tp_dictoffset */
470 	0,
471 	/* tp_init */
472 	(initproc) pyfsapfs_file_entry_init,
473 	/* tp_alloc */
474 	0,
475 	/* tp_new */
476 	0,
477 	/* tp_free */
478 	0,
479 	/* tp_is_gc */
480 	0,
481 	/* tp_bases */
482 	NULL,
483 	/* tp_mro */
484 	NULL,
485 	/* tp_cache */
486 	NULL,
487 	/* tp_subclasses */
488 	NULL,
489 	/* tp_weaklist */
490 	NULL,
491 	/* tp_del */
492 	0
493 };
494 
495 /* Creates a new file entry object
496  * Returns a Python object if successful or NULL on error
497  */
pyfsapfs_file_entry_new(libfsapfs_file_entry_t * file_entry,PyObject * parent_object)498 PyObject *pyfsapfs_file_entry_new(
499            libfsapfs_file_entry_t *file_entry,
500            PyObject *parent_object )
501 {
502 	pyfsapfs_file_entry_t *pyfsapfs_file_entry = NULL;
503 	static char *function                      = "pyfsapfs_file_entry_new";
504 
505 	if( file_entry == NULL )
506 	{
507 		PyErr_Format(
508 		 PyExc_ValueError,
509 		 "%s: invalid file entry.",
510 		 function );
511 
512 		return( NULL );
513 	}
514 	/* PyObject_New does not invoke tp_init
515 	 */
516 	pyfsapfs_file_entry = PyObject_New(
517 	                       struct pyfsapfs_file_entry,
518 	                       &pyfsapfs_file_entry_type_object );
519 
520 	if( pyfsapfs_file_entry == NULL )
521 	{
522 		PyErr_Format(
523 		 PyExc_MemoryError,
524 		 "%s: unable to initialize file entry.",
525 		 function );
526 
527 		goto on_error;
528 	}
529 	pyfsapfs_file_entry->file_entry    = file_entry;
530 	pyfsapfs_file_entry->parent_object = parent_object;
531 
532 	if( pyfsapfs_file_entry->parent_object != NULL )
533 	{
534 		Py_IncRef(
535 		 pyfsapfs_file_entry->parent_object );
536 	}
537 	return( (PyObject *) pyfsapfs_file_entry );
538 
539 on_error:
540 	if( pyfsapfs_file_entry != NULL )
541 	{
542 		Py_DecRef(
543 		 (PyObject *) pyfsapfs_file_entry );
544 	}
545 	return( NULL );
546 }
547 
548 /* Initializes a file entry object
549  * Returns 0 if successful or -1 on error
550  */
pyfsapfs_file_entry_init(pyfsapfs_file_entry_t * pyfsapfs_file_entry)551 int pyfsapfs_file_entry_init(
552      pyfsapfs_file_entry_t *pyfsapfs_file_entry )
553 {
554 	static char *function = "pyfsapfs_file_entry_init";
555 
556 	if( pyfsapfs_file_entry == NULL )
557 	{
558 		PyErr_Format(
559 		 PyExc_ValueError,
560 		 "%s: invalid file entry.",
561 		 function );
562 
563 		return( -1 );
564 	}
565 	/* Make sure libfsapfs file entry is set to NULL
566 	 */
567 	pyfsapfs_file_entry->file_entry = NULL;
568 
569 	PyErr_Format(
570 	 PyExc_NotImplementedError,
571 	 "%s: initialize of file entry not supported.",
572 	 function );
573 
574 	return( -1 );
575 }
576 
577 /* Frees a file entry object
578  */
pyfsapfs_file_entry_free(pyfsapfs_file_entry_t * pyfsapfs_file_entry)579 void pyfsapfs_file_entry_free(
580       pyfsapfs_file_entry_t *pyfsapfs_file_entry )
581 {
582 	struct _typeobject *ob_type = NULL;
583 	libcerror_error_t *error    = NULL;
584 	static char *function       = "pyfsapfs_file_entry_free";
585 	int result                  = 0;
586 
587 	if( pyfsapfs_file_entry == NULL )
588 	{
589 		PyErr_Format(
590 		 PyExc_ValueError,
591 		 "%s: invalid file entry.",
592 		 function );
593 
594 		return;
595 	}
596 	ob_type = Py_TYPE(
597 	           pyfsapfs_file_entry );
598 
599 	if( ob_type == NULL )
600 	{
601 		PyErr_Format(
602 		 PyExc_ValueError,
603 		 "%s: missing ob_type.",
604 		 function );
605 
606 		return;
607 	}
608 	if( ob_type->tp_free == NULL )
609 	{
610 		PyErr_Format(
611 		 PyExc_ValueError,
612 		 "%s: invalid ob_type - missing tp_free.",
613 		 function );
614 
615 		return;
616 	}
617 	if( pyfsapfs_file_entry->file_entry != NULL )
618 	{
619 		Py_BEGIN_ALLOW_THREADS
620 
621 		result = libfsapfs_file_entry_free(
622 		          &( pyfsapfs_file_entry->file_entry ),
623 		          &error );
624 
625 		Py_END_ALLOW_THREADS
626 
627 		if( result != 1 )
628 		{
629 			pyfsapfs_error_raise(
630 			 error,
631 			 PyExc_MemoryError,
632 			 "%s: unable to free libfsapfs file entry.",
633 			 function );
634 
635 			libcerror_error_free(
636 			 &error );
637 		}
638 	}
639 	if( pyfsapfs_file_entry->parent_object != NULL )
640 	{
641 		Py_DecRef(
642 		 pyfsapfs_file_entry->parent_object );
643 	}
644 	ob_type->tp_free(
645 	 (PyObject*) pyfsapfs_file_entry );
646 }
647 
648 /* Retrieves the identifier
649  * Returns a Python object if successful or NULL on error
650  */
pyfsapfs_file_entry_get_identifier(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)651 PyObject *pyfsapfs_file_entry_get_identifier(
652            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
653            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
654 {
655 	PyObject *integer_object = NULL;
656 	libcerror_error_t *error = NULL;
657 	static char *function    = "pyfsapfs_file_entry_get_identifier";
658 	uint64_t value_64bit     = 0;
659 	int result               = 0;
660 
661 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
662 
663 	if( pyfsapfs_file_entry == NULL )
664 	{
665 		PyErr_Format(
666 		 PyExc_ValueError,
667 		 "%s: invalid file entry.",
668 		 function );
669 
670 		return( NULL );
671 	}
672 	Py_BEGIN_ALLOW_THREADS
673 
674 	result = libfsapfs_file_entry_get_identifier(
675 	          pyfsapfs_file_entry->file_entry,
676 	          &value_64bit,
677 	          &error );
678 
679 	Py_END_ALLOW_THREADS
680 
681 	if( result != 1 )
682 	{
683 		pyfsapfs_error_raise(
684 		 error,
685 		 PyExc_IOError,
686 		 "%s: unable to retrieve identifier.",
687 		 function );
688 
689 		libcerror_error_free(
690 		 &error );
691 
692 		return( NULL );
693 	}
694 	integer_object = pyfsapfs_integer_unsigned_new_from_64bit(
695 	                  value_64bit );
696 
697 	return( integer_object );
698 }
699 
700 /* Retrieves the parent identifier
701  * Returns a Python object if successful or NULL on error
702  */
pyfsapfs_file_entry_get_parent_identifier(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)703 PyObject *pyfsapfs_file_entry_get_parent_identifier(
704            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
705            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
706 {
707 	PyObject *integer_object = NULL;
708 	libcerror_error_t *error = NULL;
709 	static char *function    = "pyfsapfs_file_entry_get_parent_identifier";
710 	uint64_t value_64bit     = 0;
711 	int result               = 0;
712 
713 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
714 
715 	if( pyfsapfs_file_entry == NULL )
716 	{
717 		PyErr_Format(
718 		 PyExc_ValueError,
719 		 "%s: invalid file entry.",
720 		 function );
721 
722 		return( NULL );
723 	}
724 	Py_BEGIN_ALLOW_THREADS
725 
726 	result = libfsapfs_file_entry_get_parent_identifier(
727 	          pyfsapfs_file_entry->file_entry,
728 	          &value_64bit,
729 	          &error );
730 
731 	Py_END_ALLOW_THREADS
732 
733 	if( result != 1 )
734 	{
735 		pyfsapfs_error_raise(
736 		 error,
737 		 PyExc_IOError,
738 		 "%s: unable to retrieve parent identifier.",
739 		 function );
740 
741 		libcerror_error_free(
742 		 &error );
743 
744 		return( NULL );
745 	}
746 	integer_object = pyfsapfs_integer_unsigned_new_from_64bit(
747 	                  value_64bit );
748 
749 	return( integer_object );
750 }
751 
752 /* Retrieves the creation date and time
753  * Returns a Python object if successful or NULL on error
754  */
pyfsapfs_file_entry_get_creation_time(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)755 PyObject *pyfsapfs_file_entry_get_creation_time(
756            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
757            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
758 {
759 	PyObject *datetime_object = NULL;
760 	libcerror_error_t *error  = NULL;
761 	static char *function     = "pyfsapfs_file_entry_get_creation_time";
762 	int64_t posix_time        = 0;
763 	int result                = 0;
764 
765 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
766 
767 	if( pyfsapfs_file_entry == NULL )
768 	{
769 		PyErr_Format(
770 		 PyExc_ValueError,
771 		 "%s: invalid file entry.",
772 		 function );
773 
774 		return( NULL );
775 	}
776 	Py_BEGIN_ALLOW_THREADS
777 
778 	result = libfsapfs_file_entry_get_creation_time(
779 	          pyfsapfs_file_entry->file_entry,
780 	          &posix_time,
781 	          &error );
782 
783 	Py_END_ALLOW_THREADS
784 
785 	if( result == -1 )
786 	{
787 		pyfsapfs_error_raise(
788 		 error,
789 		 PyExc_IOError,
790 		 "%s: unable to retrieve creation time.",
791 		 function );
792 
793 		libcerror_error_free(
794 		 &error );
795 
796 		return( NULL );
797 	}
798 	else if( result == 0 )
799 	{
800 		Py_IncRef(
801 		 Py_None );
802 
803 		return( Py_None );
804 	}
805 	datetime_object = pyfsapfs_datetime_new_from_posix_time_in_micro_seconds(
806 	                   posix_time / 1000 );
807 
808 	return( datetime_object );
809 }
810 
811 /* Retrieves the creation date and time as an integer
812  * Returns a Python object if successful or NULL on error
813  */
pyfsapfs_file_entry_get_creation_time_as_integer(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)814 PyObject *pyfsapfs_file_entry_get_creation_time_as_integer(
815            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
816            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
817 {
818 	libcerror_error_t *error = NULL;
819 	PyObject *integer_object = NULL;
820 	static char *function    = "pyfsapfs_file_entry_get_creation_time_as_integer";
821 	int64_t posix_time       = 0;
822 	int result               = 0;
823 
824 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
825 
826 	if( pyfsapfs_file_entry == NULL )
827 	{
828 		PyErr_Format(
829 		 PyExc_ValueError,
830 		 "%s: invalid file entry.",
831 		 function );
832 
833 		return( NULL );
834 	}
835 	Py_BEGIN_ALLOW_THREADS
836 
837 	result = libfsapfs_file_entry_get_creation_time(
838 	          pyfsapfs_file_entry->file_entry,
839 	          &posix_time,
840 	          &error );
841 
842 	Py_END_ALLOW_THREADS
843 
844 	if( result == -1 )
845 	{
846 		pyfsapfs_error_raise(
847 		 error,
848 		 PyExc_IOError,
849 		 "%s: unable to retrieve creation time.",
850 		 function );
851 
852 		libcerror_error_free(
853 		 &error );
854 
855 		return( NULL );
856 	}
857 	else if( result == 0 )
858 	{
859 		Py_IncRef(
860 		 Py_None );
861 
862 		return( Py_None );
863 	}
864 	integer_object = pyfsapfs_integer_signed_new_from_64bit(
865 	                  posix_time );
866 
867 	return( integer_object );
868 }
869 
870 /* Retrieves the modification date and time
871  * Returns a Python object if successful or NULL on error
872  */
pyfsapfs_file_entry_get_modification_time(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)873 PyObject *pyfsapfs_file_entry_get_modification_time(
874            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
875            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
876 {
877 	PyObject *datetime_object = NULL;
878 	libcerror_error_t *error  = NULL;
879 	static char *function     = "pyfsapfs_file_entry_get_modification_time";
880 	int64_t posix_time        = 0;
881 	int result                = 0;
882 
883 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
884 
885 	if( pyfsapfs_file_entry == NULL )
886 	{
887 		PyErr_Format(
888 		 PyExc_ValueError,
889 		 "%s: invalid file entry.",
890 		 function );
891 
892 		return( NULL );
893 	}
894 	Py_BEGIN_ALLOW_THREADS
895 
896 	result = libfsapfs_file_entry_get_modification_time(
897 	          pyfsapfs_file_entry->file_entry,
898 	          &posix_time,
899 	          &error );
900 
901 	Py_END_ALLOW_THREADS
902 
903 	if( result == -1 )
904 	{
905 		pyfsapfs_error_raise(
906 		 error,
907 		 PyExc_IOError,
908 		 "%s: unable to retrieve modification time.",
909 		 function );
910 
911 		libcerror_error_free(
912 		 &error );
913 
914 		return( NULL );
915 	}
916 	else if( result == 0 )
917 	{
918 		Py_IncRef(
919 		 Py_None );
920 
921 		return( Py_None );
922 	}
923 	datetime_object = pyfsapfs_datetime_new_from_posix_time_in_micro_seconds(
924 	                   posix_time / 1000 );
925 
926 	return( datetime_object );
927 }
928 
929 /* Retrieves the modification date and time as an integer
930  * Returns a Python object if successful or NULL on error
931  */
pyfsapfs_file_entry_get_modification_time_as_integer(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)932 PyObject *pyfsapfs_file_entry_get_modification_time_as_integer(
933            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
934            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
935 {
936 	libcerror_error_t *error = NULL;
937 	PyObject *integer_object = NULL;
938 	static char *function    = "pyfsapfs_file_entry_get_modification_time_as_integer";
939 	int64_t posix_time       = 0;
940 	int result               = 0;
941 
942 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
943 
944 	if( pyfsapfs_file_entry == NULL )
945 	{
946 		PyErr_Format(
947 		 PyExc_ValueError,
948 		 "%s: invalid file entry.",
949 		 function );
950 
951 		return( NULL );
952 	}
953 	Py_BEGIN_ALLOW_THREADS
954 
955 	result = libfsapfs_file_entry_get_modification_time(
956 	          pyfsapfs_file_entry->file_entry,
957 	          &posix_time,
958 	          &error );
959 
960 	Py_END_ALLOW_THREADS
961 
962 	if( result == -1 )
963 	{
964 		pyfsapfs_error_raise(
965 		 error,
966 		 PyExc_IOError,
967 		 "%s: unable to retrieve modification time.",
968 		 function );
969 
970 		libcerror_error_free(
971 		 &error );
972 
973 		return( NULL );
974 	}
975 	else if( result == 0 )
976 	{
977 		Py_IncRef(
978 		 Py_None );
979 
980 		return( Py_None );
981 	}
982 	integer_object = pyfsapfs_integer_signed_new_from_64bit(
983 	                  posix_time );
984 
985 	return( integer_object );
986 }
987 
988 /* Retrieves the access date and time
989  * Returns a Python object if successful or NULL on error
990  */
pyfsapfs_file_entry_get_access_time(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)991 PyObject *pyfsapfs_file_entry_get_access_time(
992            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
993            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
994 {
995 	PyObject *datetime_object = NULL;
996 	libcerror_error_t *error  = NULL;
997 	static char *function     = "pyfsapfs_file_entry_get_access_time";
998 	int64_t posix_time        = 0;
999 	int result                = 0;
1000 
1001 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1002 
1003 	if( pyfsapfs_file_entry == NULL )
1004 	{
1005 		PyErr_Format(
1006 		 PyExc_ValueError,
1007 		 "%s: invalid file entry.",
1008 		 function );
1009 
1010 		return( NULL );
1011 	}
1012 	Py_BEGIN_ALLOW_THREADS
1013 
1014 	result = libfsapfs_file_entry_get_access_time(
1015 	          pyfsapfs_file_entry->file_entry,
1016 	          &posix_time,
1017 	          &error );
1018 
1019 	Py_END_ALLOW_THREADS
1020 
1021 	if( result == -1 )
1022 	{
1023 		pyfsapfs_error_raise(
1024 		 error,
1025 		 PyExc_IOError,
1026 		 "%s: unable to retrieve access time.",
1027 		 function );
1028 
1029 		libcerror_error_free(
1030 		 &error );
1031 
1032 		return( NULL );
1033 	}
1034 	else if( result == 0 )
1035 	{
1036 		Py_IncRef(
1037 		 Py_None );
1038 
1039 		return( Py_None );
1040 	}
1041 	datetime_object = pyfsapfs_datetime_new_from_posix_time_in_micro_seconds(
1042 	                   posix_time / 1000 );
1043 
1044 	return( datetime_object );
1045 }
1046 
1047 /* Retrieves the access date and time as an integer
1048  * Returns a Python object if successful or NULL on error
1049  */
pyfsapfs_file_entry_get_access_time_as_integer(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1050 PyObject *pyfsapfs_file_entry_get_access_time_as_integer(
1051            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1052            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1053 {
1054 	libcerror_error_t *error = NULL;
1055 	PyObject *integer_object = NULL;
1056 	static char *function    = "pyfsapfs_file_entry_get_access_time_as_integer";
1057 	int64_t posix_time       = 0;
1058 	int result               = 0;
1059 
1060 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1061 
1062 	if( pyfsapfs_file_entry == NULL )
1063 	{
1064 		PyErr_Format(
1065 		 PyExc_ValueError,
1066 		 "%s: invalid file entry.",
1067 		 function );
1068 
1069 		return( NULL );
1070 	}
1071 	Py_BEGIN_ALLOW_THREADS
1072 
1073 	result = libfsapfs_file_entry_get_access_time(
1074 	          pyfsapfs_file_entry->file_entry,
1075 	          &posix_time,
1076 	          &error );
1077 
1078 	Py_END_ALLOW_THREADS
1079 
1080 	if( result == -1 )
1081 	{
1082 		pyfsapfs_error_raise(
1083 		 error,
1084 		 PyExc_IOError,
1085 		 "%s: unable to retrieve access time.",
1086 		 function );
1087 
1088 		libcerror_error_free(
1089 		 &error );
1090 
1091 		return( NULL );
1092 	}
1093 	else if( result == 0 )
1094 	{
1095 		Py_IncRef(
1096 		 Py_None );
1097 
1098 		return( Py_None );
1099 	}
1100 	integer_object = pyfsapfs_integer_signed_new_from_64bit(
1101 	                  posix_time );
1102 
1103 	return( integer_object );
1104 }
1105 
1106 /* Retrieves the inode change date and time
1107  * Returns a Python object if successful or NULL on error
1108  */
pyfsapfs_file_entry_get_inode_change_time(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1109 PyObject *pyfsapfs_file_entry_get_inode_change_time(
1110            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1111            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1112 {
1113 	PyObject *datetime_object = NULL;
1114 	libcerror_error_t *error  = NULL;
1115 	static char *function     = "pyfsapfs_file_entry_get_inode_change_time";
1116 	int64_t posix_time        = 0;
1117 	int result                = 0;
1118 
1119 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1120 
1121 	if( pyfsapfs_file_entry == NULL )
1122 	{
1123 		PyErr_Format(
1124 		 PyExc_ValueError,
1125 		 "%s: invalid file entry.",
1126 		 function );
1127 
1128 		return( NULL );
1129 	}
1130 	Py_BEGIN_ALLOW_THREADS
1131 
1132 	result = libfsapfs_file_entry_get_inode_change_time(
1133 	          pyfsapfs_file_entry->file_entry,
1134 	          &posix_time,
1135 	          &error );
1136 
1137 	Py_END_ALLOW_THREADS
1138 
1139 	if( result == -1 )
1140 	{
1141 		pyfsapfs_error_raise(
1142 		 error,
1143 		 PyExc_IOError,
1144 		 "%s: unable to retrieve inode change time.",
1145 		 function );
1146 
1147 		libcerror_error_free(
1148 		 &error );
1149 
1150 		return( NULL );
1151 	}
1152 	else if( result == 0 )
1153 	{
1154 		Py_IncRef(
1155 		 Py_None );
1156 
1157 		return( Py_None );
1158 	}
1159 	datetime_object = pyfsapfs_datetime_new_from_posix_time_in_micro_seconds(
1160 	                   posix_time / 1000 );
1161 
1162 	return( datetime_object );
1163 }
1164 
1165 /* Retrieves the inode change date and time as an integer
1166  * Returns a Python object if successful or NULL on error
1167  */
pyfsapfs_file_entry_get_inode_change_time_as_integer(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1168 PyObject *pyfsapfs_file_entry_get_inode_change_time_as_integer(
1169            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1170            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1171 {
1172 	libcerror_error_t *error = NULL;
1173 	PyObject *integer_object = NULL;
1174 	static char *function    = "pyfsapfs_file_entry_get_inode_change_time_as_integer";
1175 	int64_t posix_time       = 0;
1176 	int result               = 0;
1177 
1178 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1179 
1180 	if( pyfsapfs_file_entry == NULL )
1181 	{
1182 		PyErr_Format(
1183 		 PyExc_ValueError,
1184 		 "%s: invalid file entry.",
1185 		 function );
1186 
1187 		return( NULL );
1188 	}
1189 	Py_BEGIN_ALLOW_THREADS
1190 
1191 	result = libfsapfs_file_entry_get_inode_change_time(
1192 	          pyfsapfs_file_entry->file_entry,
1193 	          &posix_time,
1194 	          &error );
1195 
1196 	Py_END_ALLOW_THREADS
1197 
1198 	if( result == -1 )
1199 	{
1200 		pyfsapfs_error_raise(
1201 		 error,
1202 		 PyExc_IOError,
1203 		 "%s: unable to retrieve inode change time.",
1204 		 function );
1205 
1206 		libcerror_error_free(
1207 		 &error );
1208 
1209 		return( NULL );
1210 	}
1211 	else if( result == 0 )
1212 	{
1213 		Py_IncRef(
1214 		 Py_None );
1215 
1216 		return( Py_None );
1217 	}
1218 	integer_object = pyfsapfs_integer_signed_new_from_64bit(
1219 	                  posix_time );
1220 
1221 	return( integer_object );
1222 }
1223 
1224 /* Retrieves the added date and time
1225  * Returns a Python object if successful or NULL on error
1226  */
pyfsapfs_file_entry_get_added_time(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1227 PyObject *pyfsapfs_file_entry_get_added_time(
1228            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1229            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1230 {
1231 	PyObject *datetime_object = NULL;
1232 	libcerror_error_t *error  = NULL;
1233 	static char *function     = "pyfsapfs_file_entry_get_added_time";
1234 	int64_t posix_time        = 0;
1235 	int result                = 0;
1236 
1237 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1238 
1239 	if( pyfsapfs_file_entry == NULL )
1240 	{
1241 		PyErr_Format(
1242 		 PyExc_ValueError,
1243 		 "%s: invalid file entry.",
1244 		 function );
1245 
1246 		return( NULL );
1247 	}
1248 	Py_BEGIN_ALLOW_THREADS
1249 
1250 	result = libfsapfs_file_entry_get_added_time(
1251 	          pyfsapfs_file_entry->file_entry,
1252 	          &posix_time,
1253 	          &error );
1254 
1255 	Py_END_ALLOW_THREADS
1256 
1257 	if( result == -1 )
1258 	{
1259 		pyfsapfs_error_raise(
1260 		 error,
1261 		 PyExc_IOError,
1262 		 "%s: unable to retrieve added time.",
1263 		 function );
1264 
1265 		libcerror_error_free(
1266 		 &error );
1267 
1268 		return( NULL );
1269 	}
1270 	else if( result == 0 )
1271 	{
1272 		Py_IncRef(
1273 		 Py_None );
1274 
1275 		return( Py_None );
1276 	}
1277 	datetime_object = pyfsapfs_datetime_new_from_posix_time_in_micro_seconds(
1278 	                   posix_time / 1000 );
1279 
1280 	return( datetime_object );
1281 }
1282 
1283 /* Retrieves the added date and time as an integer
1284  * Returns a Python object if successful or NULL on error
1285  */
pyfsapfs_file_entry_get_added_time_as_integer(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1286 PyObject *pyfsapfs_file_entry_get_added_time_as_integer(
1287            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1288            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1289 {
1290 	libcerror_error_t *error = NULL;
1291 	PyObject *integer_object = NULL;
1292 	static char *function    = "pyfsapfs_file_entry_get_added_time_as_integer";
1293 	int64_t posix_time       = 0;
1294 	int result               = 0;
1295 
1296 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1297 
1298 	if( pyfsapfs_file_entry == NULL )
1299 	{
1300 		PyErr_Format(
1301 		 PyExc_ValueError,
1302 		 "%s: invalid file entry.",
1303 		 function );
1304 
1305 		return( NULL );
1306 	}
1307 	Py_BEGIN_ALLOW_THREADS
1308 
1309 	result = libfsapfs_file_entry_get_added_time(
1310 	          pyfsapfs_file_entry->file_entry,
1311 	          &posix_time,
1312 	          &error );
1313 
1314 	Py_END_ALLOW_THREADS
1315 
1316 	if( result == -1 )
1317 	{
1318 		pyfsapfs_error_raise(
1319 		 error,
1320 		 PyExc_IOError,
1321 		 "%s: unable to retrieve added time.",
1322 		 function );
1323 
1324 		libcerror_error_free(
1325 		 &error );
1326 
1327 		return( NULL );
1328 	}
1329 	else if( result == 0 )
1330 	{
1331 		Py_IncRef(
1332 		 Py_None );
1333 
1334 		return( Py_None );
1335 	}
1336 	integer_object = pyfsapfs_integer_signed_new_from_64bit(
1337 	                  posix_time );
1338 
1339 	return( integer_object );
1340 }
1341 
1342 /* Retrieves the owner identifier
1343  * Returns a Python object if successful or NULL on error
1344  */
pyfsapfs_file_entry_get_owner_identifier(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1345 PyObject *pyfsapfs_file_entry_get_owner_identifier(
1346            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1347            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1348 {
1349 	PyObject *integer_object = NULL;
1350 	libcerror_error_t *error = NULL;
1351 	static char *function    = "pyfsapfs_file_entry_get_owner_identifier";
1352 	uint32_t value_32bit     = 0;
1353 	int result               = 0;
1354 
1355 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1356 
1357 	if( pyfsapfs_file_entry == NULL )
1358 	{
1359 		PyErr_Format(
1360 		 PyExc_ValueError,
1361 		 "%s: invalid file entry.",
1362 		 function );
1363 
1364 		return( NULL );
1365 	}
1366 	Py_BEGIN_ALLOW_THREADS
1367 
1368 	result = libfsapfs_file_entry_get_owner_identifier(
1369 	          pyfsapfs_file_entry->file_entry,
1370 	          &value_32bit,
1371 	          &error );
1372 
1373 	Py_END_ALLOW_THREADS
1374 
1375 	if( result != 1 )
1376 	{
1377 		pyfsapfs_error_raise(
1378 		 error,
1379 		 PyExc_IOError,
1380 		 "%s: unable to retrieve .",
1381 		 function );
1382 
1383 		libcerror_error_free(
1384 		 &error );
1385 
1386 		return( NULL );
1387 	}
1388 	integer_object = PyLong_FromUnsignedLong(
1389 	                  (unsigned long) value_32bit );
1390 
1391 	return( integer_object );
1392 }
1393 
1394 /* Retrieves the group identifier
1395  * Returns a Python object if successful or NULL on error
1396  */
pyfsapfs_file_entry_get_group_identifier(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1397 PyObject *pyfsapfs_file_entry_get_group_identifier(
1398            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1399            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1400 {
1401 	PyObject *integer_object = NULL;
1402 	libcerror_error_t *error = NULL;
1403 	static char *function    = "pyfsapfs_file_entry_get_group_identifier";
1404 	uint32_t value_32bit     = 0;
1405 	int result               = 0;
1406 
1407 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1408 
1409 	if( pyfsapfs_file_entry == NULL )
1410 	{
1411 		PyErr_Format(
1412 		 PyExc_ValueError,
1413 		 "%s: invalid file entry.",
1414 		 function );
1415 
1416 		return( NULL );
1417 	}
1418 	Py_BEGIN_ALLOW_THREADS
1419 
1420 	result = libfsapfs_file_entry_get_group_identifier(
1421 	          pyfsapfs_file_entry->file_entry,
1422 	          &value_32bit,
1423 	          &error );
1424 
1425 	Py_END_ALLOW_THREADS
1426 
1427 	if( result != 1 )
1428 	{
1429 		pyfsapfs_error_raise(
1430 		 error,
1431 		 PyExc_IOError,
1432 		 "%s: unable to retrieve .",
1433 		 function );
1434 
1435 		libcerror_error_free(
1436 		 &error );
1437 
1438 		return( NULL );
1439 	}
1440 	integer_object = PyLong_FromUnsignedLong(
1441 	                  (unsigned long) value_32bit );
1442 
1443 	return( integer_object );
1444 }
1445 
1446 /* Retrieves the file mode
1447  * Returns a Python object if successful or NULL on error
1448  */
pyfsapfs_file_entry_get_file_mode(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1449 PyObject *pyfsapfs_file_entry_get_file_mode(
1450            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1451            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1452 {
1453 	PyObject *integer_object = NULL;
1454 	libcerror_error_t *error = NULL;
1455 	static char *function    = "pyfsapfs_file_entry_get_file_mode";
1456 	uint16_t file_mode       = 0;
1457 	int result               = 0;
1458 
1459 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1460 
1461 	if( pyfsapfs_file_entry == NULL )
1462 	{
1463 		PyErr_Format(
1464 		 PyExc_ValueError,
1465 		 "%s: invalid file entry.",
1466 		 function );
1467 
1468 		return( NULL );
1469 	}
1470 	Py_BEGIN_ALLOW_THREADS
1471 
1472 	result = libfsapfs_file_entry_get_file_mode(
1473 	          pyfsapfs_file_entry->file_entry,
1474 	          &file_mode,
1475 	          &error );
1476 
1477 	Py_END_ALLOW_THREADS
1478 
1479 	if( result != 1 )
1480 	{
1481 		pyfsapfs_error_raise(
1482 		 error,
1483 		 PyExc_IOError,
1484 		 "%s: unable to retrieve .",
1485 		 function );
1486 
1487 		libcerror_error_free(
1488 		 &error );
1489 
1490 		return( NULL );
1491 	}
1492 #if PY_MAJOR_VERSION >= 3
1493 	integer_object = PyLong_FromLong(
1494 	                  (long) file_mode );
1495 #else
1496 	integer_object = PyInt_FromLong(
1497 	                  (long) file_mode );
1498 #endif
1499 	return( integer_object );
1500 }
1501 
1502 /* Retrieves the name
1503  * Returns a Python object if successful or NULL on error
1504  */
pyfsapfs_file_entry_get_name(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1505 PyObject *pyfsapfs_file_entry_get_name(
1506            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1507            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1508 {
1509 	PyObject *string_object  = NULL;
1510 	libcerror_error_t *error = NULL;
1511 	const char *errors       = NULL;
1512 	static char *function    = "pyfsapfs_file_entry_get_name";
1513 	char *utf8_string        = NULL;
1514 	size_t utf8_string_size  = 0;
1515 	int result               = 0;
1516 
1517 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1518 
1519 	if( pyfsapfs_file_entry == NULL )
1520 	{
1521 		PyErr_Format(
1522 		 PyExc_ValueError,
1523 		 "%s: invalid file entry.",
1524 		 function );
1525 
1526 		return( NULL );
1527 	}
1528 	Py_BEGIN_ALLOW_THREADS
1529 
1530 	result = libfsapfs_file_entry_get_utf8_name_size(
1531 	          pyfsapfs_file_entry->file_entry,
1532 	          &utf8_string_size,
1533 	          &error );
1534 
1535 	Py_END_ALLOW_THREADS
1536 
1537 	if( result == -1 )
1538 	{
1539 		pyfsapfs_error_raise(
1540 		 error,
1541 		 PyExc_IOError,
1542 		 "%s: unable to determine size of  as UTF-8 string.",
1543 		 function );
1544 
1545 		libcerror_error_free(
1546 		 &error );
1547 
1548 		goto on_error;
1549 	}
1550 	else if( ( result == 0 )
1551 	      || ( utf8_string_size == 0 ) )
1552 	{
1553 		Py_IncRef(
1554 		 Py_None );
1555 
1556 		return( Py_None );
1557 	}
1558 	utf8_string = (char *) PyMem_Malloc(
1559 	                        sizeof( char ) * utf8_string_size );
1560 
1561 	if( utf8_string == NULL )
1562 	{
1563 		PyErr_Format(
1564 		 PyExc_MemoryError,
1565 		 "%s: unable to create UTF-8 string.",
1566 		 function );
1567 
1568 		goto on_error;
1569 	}
1570 	Py_BEGIN_ALLOW_THREADS
1571 
1572 	result = libfsapfs_file_entry_get_utf8_name(
1573 	          pyfsapfs_file_entry->file_entry,
1574 	          (uint8_t *) utf8_string,
1575 	          utf8_string_size,
1576 	          &error );
1577 
1578 	Py_END_ALLOW_THREADS
1579 
1580 	if( result != 1 )
1581 	{
1582 		pyfsapfs_error_raise(
1583 		 error,
1584 		 PyExc_IOError,
1585 		 "%s: unable to retrieve  as UTF-8 string.",
1586 		 function );
1587 
1588 		libcerror_error_free(
1589 		 &error );
1590 
1591 		goto on_error;
1592 	}
1593 	/* Pass the string length to PyUnicode_DecodeUTF8 otherwise it makes
1594 	 * the end of string character is part of the string.
1595 	 */
1596 	string_object = PyUnicode_DecodeUTF8(
1597 	                 utf8_string,
1598 	                 (Py_ssize_t) utf8_string_size - 1,
1599 	                 errors );
1600 
1601 	if( string_object == NULL )
1602 	{
1603 		PyErr_Format(
1604 		 PyExc_IOError,
1605 		 "%s: unable to convert UTF-8 string into Unicode object.",
1606 		 function );
1607 
1608 		goto on_error;
1609 	}
1610 	PyMem_Free(
1611 	 utf8_string );
1612 
1613 	return( string_object );
1614 
1615 on_error:
1616 	if( utf8_string != NULL )
1617 	{
1618 		PyMem_Free(
1619 		 utf8_string );
1620 	}
1621 	return( NULL );
1622 }
1623 
1624 /* Retrieves the symbolic link target
1625  * Returns a Python object if successful or NULL on error
1626  */
pyfsapfs_file_entry_get_symbolic_link_target(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1627 PyObject *pyfsapfs_file_entry_get_symbolic_link_target(
1628            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1629            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1630 {
1631 	libcerror_error_t *error = NULL;
1632 	PyObject *string_object  = NULL;
1633 	const char *errors       = NULL;
1634 	uint8_t *target          = NULL;
1635 	static char *function    = "pyfsapfs_file_entry_get_symbolic_link_target";
1636 	size_t target_size       = 0;
1637 	int result               = 0;
1638 
1639 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1640 
1641 	if( pyfsapfs_file_entry == NULL )
1642 	{
1643 		PyErr_Format(
1644 		 PyExc_TypeError,
1645 		 "%s: invalid file entry.",
1646 		 function );
1647 
1648 		return( NULL );
1649 	}
1650 	Py_BEGIN_ALLOW_THREADS
1651 
1652 	result = libfsapfs_file_entry_get_utf8_symbolic_link_target_size(
1653 	          pyfsapfs_file_entry->file_entry,
1654 	          &target_size,
1655 	          &error );
1656 
1657 	Py_END_ALLOW_THREADS
1658 
1659 	if( result == -1 )
1660 	{
1661 		pyfsapfs_error_raise(
1662 		 error,
1663 		 PyExc_IOError,
1664 		 "%s: unable to retrieve symbolic link target size.",
1665 		 function );
1666 
1667 		libcerror_error_free(
1668 		 &error );
1669 
1670 		goto on_error;
1671 	}
1672 	else if( ( result == 0 )
1673 	      || ( target_size == 0 ) )
1674 	{
1675 		Py_IncRef(
1676 		 Py_None );
1677 
1678 		return( Py_None );
1679 	}
1680 	target = (uint8_t *) PyMem_Malloc(
1681 	                      sizeof( uint8_t ) * target_size );
1682 
1683 	if( target == NULL )
1684 	{
1685 		PyErr_Format(
1686 		 PyExc_IOError,
1687 		 "%s: unable to create target.",
1688 		 function );
1689 
1690 		goto on_error;
1691 	}
1692 	Py_BEGIN_ALLOW_THREADS
1693 
1694 	result = libfsapfs_file_entry_get_utf8_symbolic_link_target(
1695 		  pyfsapfs_file_entry->file_entry,
1696 		  target,
1697 		  target_size,
1698 		  &error );
1699 
1700 	Py_END_ALLOW_THREADS
1701 
1702 	if( result != 1 )
1703 	{
1704 		pyfsapfs_error_raise(
1705 		 error,
1706 		 PyExc_IOError,
1707 		 "%s: unable to retrieve symbolic link target.",
1708 		 function );
1709 
1710 		libcerror_error_free(
1711 		 &error );
1712 
1713 		goto on_error;
1714 	}
1715 	/* Pass the string length to PyUnicode_DecodeUTF8
1716 	 * otherwise it makes the end of string character is part
1717 	 * of the string
1718 	 */
1719 	string_object = PyUnicode_DecodeUTF8(
1720 			 (char *) target,
1721 			 (Py_ssize_t) target_size - 1,
1722 			 errors );
1723 
1724 	PyMem_Free(
1725 	 target );
1726 
1727 	return( string_object );
1728 
1729 on_error:
1730 	if( target != NULL )
1731 	{
1732 		PyMem_Free(
1733 		 target );
1734 	}
1735 	return( NULL );
1736 }
1737 
1738 /* Retrieves the number of extended attributes
1739  * Returns a Python object if successful or NULL on error
1740  */
pyfsapfs_file_entry_get_number_of_extended_attributes(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1741 PyObject *pyfsapfs_file_entry_get_number_of_extended_attributes(
1742            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1743            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1744 {
1745 	PyObject *integer_object          = NULL;
1746 	libcerror_error_t *error          = NULL;
1747 	static char *function             = "pyfsapfs_file_entry_get_number_of_extended_attributes";
1748 	int number_of_extended_attributes = 0;
1749 	int result                        = 0;
1750 
1751 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1752 
1753 	if( pyfsapfs_file_entry == NULL )
1754 	{
1755 		PyErr_Format(
1756 		 PyExc_ValueError,
1757 		 "%s: invalid file entry.",
1758 		 function );
1759 
1760 		return( NULL );
1761 	}
1762 	Py_BEGIN_ALLOW_THREADS
1763 
1764 	result = libfsapfs_file_entry_get_number_of_extended_attributes(
1765 	          pyfsapfs_file_entry->file_entry,
1766 	          &number_of_extended_attributes,
1767 	          &error );
1768 
1769 	Py_END_ALLOW_THREADS
1770 
1771 	if( result != 1 )
1772 	{
1773 		pyfsapfs_error_raise(
1774 		 error,
1775 		 PyExc_IOError,
1776 		 "%s: unable to retrieve .",
1777 		 function );
1778 
1779 		libcerror_error_free(
1780 		 &error );
1781 
1782 		return( NULL );
1783 	}
1784 #if PY_MAJOR_VERSION >= 3
1785 	integer_object = PyLong_FromLong(
1786 	                  (long) number_of_extended_attributes );
1787 #else
1788 	integer_object = PyInt_FromLong(
1789 	                  (long) number_of_extended_attributes );
1790 #endif
1791 	return( integer_object );
1792 }
1793 
1794 /* Retrieves a specific extended attribute by index
1795  * Returns a Python object if successful or NULL on error
1796  */
pyfsapfs_file_entry_get_extended_attribute_by_index(PyObject * pyfsapfs_file_entry,int extended_attribute_index)1797 PyObject *pyfsapfs_file_entry_get_extended_attribute_by_index(
1798            PyObject *pyfsapfs_file_entry,
1799            int extended_attribute_index )
1800 {
1801 	PyObject *extended_attribute_object                = NULL;
1802 	libcerror_error_t *error                           = NULL;
1803 	libfsapfs_extended_attribute_t *extended_attribute = NULL;
1804 	static char *function                              = "pyfsapfs_file_entry_get_extended_attribute_by_index";
1805 	int result                                         = 0;
1806 
1807 	if( pyfsapfs_file_entry == NULL )
1808 	{
1809 		PyErr_Format(
1810 		 PyExc_ValueError,
1811 		 "%s: invalid file entry.",
1812 		 function );
1813 
1814 		return( NULL );
1815 	}
1816 	Py_BEGIN_ALLOW_THREADS
1817 
1818 	result = libfsapfs_file_entry_get_extended_attribute_by_index(
1819 	          ( (pyfsapfs_file_entry_t *) pyfsapfs_file_entry )->file_entry,
1820 	          extended_attribute_index,
1821 	          &extended_attribute,
1822 	          &error );
1823 
1824 	Py_END_ALLOW_THREADS
1825 
1826 	if( result != 1 )
1827 	{
1828 		pyfsapfs_error_raise(
1829 		 error,
1830 		 PyExc_IOError,
1831 		 "%s: unable to retrieve : %d.",
1832 		 function,
1833 		 extended_attribute_index );
1834 
1835 		libcerror_error_free(
1836 		 &error );
1837 
1838 		goto on_error;
1839 	}
1840 	extended_attribute_object = pyfsapfs_extended_attribute_new(
1841 	                             extended_attribute,
1842 	                             pyfsapfs_file_entry );
1843 
1844 	if( extended_attribute_object == NULL )
1845 	{
1846 		PyErr_Format(
1847 		 PyExc_MemoryError,
1848 		 "%s: unable to create extended attribute object.",
1849 		 function );
1850 
1851 		goto on_error;
1852 	}
1853 	return( extended_attribute_object );
1854 
1855 on_error:
1856 	if( extended_attribute != NULL )
1857 	{
1858 		libfsapfs_extended_attribute_free(
1859 		 &extended_attribute,
1860 		 NULL );
1861 	}
1862 	return( NULL );
1863 }
1864 
1865 /* Retrieves a specific extended attribute
1866  * Returns a Python object if successful or NULL on error
1867  */
pyfsapfs_file_entry_get_extended_attribute(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments,PyObject * keywords)1868 PyObject *pyfsapfs_file_entry_get_extended_attribute(
1869            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1870            PyObject *arguments,
1871            PyObject *keywords )
1872 {
1873 	PyObject *extended_attribute_object = NULL;
1874 	static char *keyword_list[]         = { "extended_attribute_index", NULL };
1875 	int extended_attribute_index        = 0;
1876 
1877 	if( PyArg_ParseTupleAndKeywords(
1878 	     arguments,
1879 	     keywords,
1880 	     "i",
1881 	     keyword_list,
1882 	     &extended_attribute_index ) == 0 )
1883 	{
1884 		return( NULL );
1885 	}
1886 	extended_attribute_object = pyfsapfs_file_entry_get_extended_attribute_by_index(
1887 	                             (PyObject *) pyfsapfs_file_entry,
1888 	                             extended_attribute_index );
1889 
1890 	return( extended_attribute_object );
1891 }
1892 
1893 /* Retrieves a sequence and iterator object for the extended attributes
1894  * Returns a Python object if successful or NULL on error
1895  */
pyfsapfs_file_entry_get_extended_attributes(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)1896 PyObject *pyfsapfs_file_entry_get_extended_attributes(
1897            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1898            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
1899 {
1900 	PyObject *sequence_object         = NULL;
1901 	libcerror_error_t *error          = NULL;
1902 	static char *function             = "pyfsapfs_file_entry_get_extended_attributes";
1903 	int number_of_extended_attributes = 0;
1904 	int result                        = 0;
1905 
1906 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
1907 
1908 	if( pyfsapfs_file_entry == NULL )
1909 	{
1910 		PyErr_Format(
1911 		 PyExc_ValueError,
1912 		 "%s: invalid file entry.",
1913 		 function );
1914 
1915 		return( NULL );
1916 	}
1917 	Py_BEGIN_ALLOW_THREADS
1918 
1919 	result = libfsapfs_file_entry_get_number_of_extended_attributes(
1920 	          pyfsapfs_file_entry->file_entry,
1921 	          &number_of_extended_attributes,
1922 	          &error );
1923 
1924 	Py_END_ALLOW_THREADS
1925 
1926 	if( result != 1 )
1927 	{
1928 		pyfsapfs_error_raise(
1929 		 error,
1930 		 PyExc_IOError,
1931 		 "%s: unable to retrieve number of extended attributes.",
1932 		 function );
1933 
1934 		libcerror_error_free(
1935 		 &error );
1936 
1937 		return( NULL );
1938 	}
1939 	sequence_object = pyfsapfs_extended_attributes_new(
1940 	                   (PyObject *) pyfsapfs_file_entry,
1941 	                   &pyfsapfs_file_entry_get_extended_attribute_by_index,
1942 	                   number_of_extended_attributes );
1943 
1944 	if( sequence_object == NULL )
1945 	{
1946 		pyfsapfs_error_raise(
1947 		 error,
1948 		 PyExc_MemoryError,
1949 		 "%s: unable to create sequence object.",
1950 		 function );
1951 
1952 		return( NULL );
1953 	}
1954 	return( sequence_object );
1955 }
1956 
1957 /* Determines if there is an extended attribute specified by the name
1958  * Returns a Python object if successful or NULL on error
1959  */
pyfsapfs_file_entry_has_extended_attribute_by_name(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments,PyObject * keywords)1960 PyObject *pyfsapfs_file_entry_has_extended_attribute_by_name(
1961            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
1962            PyObject *arguments,
1963            PyObject *keywords )
1964 {
1965 	libcerror_error_t *error              = NULL;
1966 	char *extended_attribute_name         = NULL;
1967 	static char *keyword_list[]           = { "extended_attribute_name", NULL };
1968 	static char *function                 = "pyfsapfs_file_entry_has_extended_attribute_by_name";
1969 	size_t extended_attribute_name_length = 0;
1970 	int result                            = 0;
1971 
1972 	if( pyfsapfs_file_entry == NULL )
1973 	{
1974 		PyErr_Format(
1975 		 PyExc_TypeError,
1976 		 "%s: invalid file entry.",
1977 		 function );
1978 
1979 		return( NULL );
1980 	}
1981 	if( PyArg_ParseTupleAndKeywords(
1982 	     arguments,
1983 	     keywords,
1984 	     "s",
1985 	     keyword_list,
1986 	     &extended_attribute_name ) == 0 )
1987 	{
1988 		return( NULL );
1989 	}
1990 	extended_attribute_name_length = narrow_string_length(
1991 	                                  extended_attribute_name );
1992 
1993 	Py_BEGIN_ALLOW_THREADS
1994 
1995 	result = libfsapfs_file_entry_has_extended_attribute_by_utf8_name(
1996 	           pyfsapfs_file_entry->file_entry,
1997 	           (uint8_t *) extended_attribute_name,
1998 	           extended_attribute_name_length,
1999 	           &error );
2000 
2001 	Py_END_ALLOW_THREADS
2002 
2003 	if( result == -1 )
2004 	{
2005 		pyfsapfs_error_raise(
2006 		 error,
2007 		 PyExc_IOError,
2008 		 "%s: unable to determine if extended attribute exists.",
2009 		 function );
2010 
2011 		libcerror_error_free(
2012 		 &error );
2013 
2014 		return( NULL );
2015 	}
2016 	/* Check if the extended attribute is present
2017 	 */
2018 	if( result != 0 )
2019 	{
2020 		Py_IncRef(
2021 		 (PyObject *) Py_True );
2022 
2023 		return( Py_True );
2024 	}
2025 	Py_IncRef(
2026 	 (PyObject *) Py_False );
2027 
2028 	return( Py_False );
2029 }
2030 
2031 /* Retrieves the extended attribute specified by the name
2032  * Returns a Python object if successful or NULL on error
2033  */
pyfsapfs_file_entry_get_extended_attribute_by_name(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments,PyObject * keywords)2034 PyObject *pyfsapfs_file_entry_get_extended_attribute_by_name(
2035            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
2036            PyObject *arguments,
2037            PyObject *keywords )
2038 {
2039 	libcerror_error_t *error                           = NULL;
2040 	libfsapfs_extended_attribute_t *extended_attribute = NULL;
2041 	PyObject *extended_attribute_object                = NULL;
2042 	char *extended_attribute_name                      = NULL;
2043 	static char *keyword_list[]                        = { "extended_attribute_name", NULL };
2044 	static char *function                              = "pyfsapfs_file_entry_get_extended_attribute_by_name";
2045 	size_t extended_attribute_name_length              = 0;
2046 	int result                                         = 0;
2047 
2048 	if( pyfsapfs_file_entry == NULL )
2049 	{
2050 		PyErr_Format(
2051 		 PyExc_TypeError,
2052 		 "%s: invalid file entry.",
2053 		 function );
2054 
2055 		return( NULL );
2056 	}
2057 	if( PyArg_ParseTupleAndKeywords(
2058 	     arguments,
2059 	     keywords,
2060 	     "s",
2061 	     keyword_list,
2062 	     &extended_attribute_name ) == 0 )
2063 	{
2064 		goto on_error;
2065 	}
2066 	extended_attribute_name_length = narrow_string_length(
2067 	                                  extended_attribute_name );
2068 
2069 	Py_BEGIN_ALLOW_THREADS
2070 
2071 	result = libfsapfs_file_entry_get_extended_attribute_by_utf8_name(
2072 	           pyfsapfs_file_entry->file_entry,
2073 	           (uint8_t *) extended_attribute_name,
2074 	           extended_attribute_name_length,
2075 	           &extended_attribute,
2076 	           &error );
2077 
2078 	Py_END_ALLOW_THREADS
2079 
2080 	if( result == -1 )
2081 	{
2082 		pyfsapfs_error_raise(
2083 		 error,
2084 		 PyExc_IOError,
2085 		 "%s: unable to retrieve extended attribute.",
2086 		 function );
2087 
2088 		libcerror_error_free(
2089 		 &error );
2090 
2091 		goto on_error;
2092 	}
2093 	/* Check if the extended attribute is present
2094 	 */
2095 	else if( result == 0 )
2096 	{
2097 		Py_IncRef(
2098 		 Py_None );
2099 
2100 		return( Py_None );
2101 	}
2102 	extended_attribute_object = pyfsapfs_extended_attribute_new(
2103 	                             extended_attribute,
2104 	                             (PyObject *) pyfsapfs_file_entry );
2105 
2106 	if( extended_attribute_object == NULL )
2107 	{
2108 		PyErr_Format(
2109 		 PyExc_MemoryError,
2110 		 "%s: unable to create extended attribute object.",
2111 		 function );
2112 
2113 		goto on_error;
2114 	}
2115 	return( extended_attribute_object );
2116 
2117 on_error:
2118 	if( extended_attribute != NULL )
2119 	{
2120 		libfsapfs_extended_attribute_free(
2121 		 &extended_attribute,
2122 		 NULL );
2123 	}
2124 	return( NULL );
2125 }
2126 
2127 /* Retrieves the number of sub file entries
2128  * Returns a Python object if successful or NULL on error
2129  */
pyfsapfs_file_entry_get_number_of_sub_file_entries(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)2130 PyObject *pyfsapfs_file_entry_get_number_of_sub_file_entries(
2131            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
2132            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
2133 {
2134 	PyObject *integer_object       = NULL;
2135 	libcerror_error_t *error       = NULL;
2136 	static char *function          = "pyfsapfs_file_entry_get_number_of_sub_file_entries";
2137 	int number_of_sub_file_entries = 0;
2138 	int result                     = 0;
2139 
2140 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
2141 
2142 	if( pyfsapfs_file_entry == NULL )
2143 	{
2144 		PyErr_Format(
2145 		 PyExc_ValueError,
2146 		 "%s: invalid file entry.",
2147 		 function );
2148 
2149 		return( NULL );
2150 	}
2151 	Py_BEGIN_ALLOW_THREADS
2152 
2153 	result = libfsapfs_file_entry_get_number_of_sub_file_entries(
2154 	          pyfsapfs_file_entry->file_entry,
2155 	          &number_of_sub_file_entries,
2156 	          &error );
2157 
2158 	Py_END_ALLOW_THREADS
2159 
2160 	if( result != 1 )
2161 	{
2162 		pyfsapfs_error_raise(
2163 		 error,
2164 		 PyExc_IOError,
2165 		 "%s: unable to retrieve .",
2166 		 function );
2167 
2168 		libcerror_error_free(
2169 		 &error );
2170 
2171 		return( NULL );
2172 	}
2173 #if PY_MAJOR_VERSION >= 3
2174 	integer_object = PyLong_FromLong(
2175 	                  (long) number_of_sub_file_entries );
2176 #else
2177 	integer_object = PyInt_FromLong(
2178 	                  (long) number_of_sub_file_entries );
2179 #endif
2180 	return( integer_object );
2181 }
2182 
2183 /* Retrieves a specific of sub file entry by index
2184  * Returns a Python object if successful or NULL on error
2185  */
pyfsapfs_file_entry_get_sub_file_entry_by_index(PyObject * pyfsapfs_file_entry,int sub_file_entry_index)2186 PyObject *pyfsapfs_file_entry_get_sub_file_entry_by_index(
2187            PyObject *pyfsapfs_file_entry,
2188            int sub_file_entry_index )
2189 {
2190 	PyObject *file_entry_object            = NULL;
2191 	libcerror_error_t *error               = NULL;
2192 	libfsapfs_file_entry_t *sub_file_entry = NULL;
2193 	static char *function                  = "pyfsapfs_file_entry_get_sub_file_entry_by_index";
2194 	int result                             = 0;
2195 
2196 	if( pyfsapfs_file_entry == NULL )
2197 	{
2198 		PyErr_Format(
2199 		 PyExc_ValueError,
2200 		 "%s: invalid file entry.",
2201 		 function );
2202 
2203 		return( NULL );
2204 	}
2205 	Py_BEGIN_ALLOW_THREADS
2206 
2207 	result = libfsapfs_file_entry_get_sub_file_entry_by_index(
2208 	          ( (pyfsapfs_file_entry_t *) pyfsapfs_file_entry )->file_entry,
2209 	          sub_file_entry_index,
2210 	          &sub_file_entry,
2211 	          &error );
2212 
2213 	Py_END_ALLOW_THREADS
2214 
2215 	if( result != 1 )
2216 	{
2217 		pyfsapfs_error_raise(
2218 		 error,
2219 		 PyExc_IOError,
2220 		 "%s: unable to retrieve sub : %d.",
2221 		 function,
2222 		 sub_file_entry_index );
2223 
2224 		libcerror_error_free(
2225 		 &error );
2226 
2227 		goto on_error;
2228 	}
2229 	file_entry_object = pyfsapfs_file_entry_new(
2230 	                     sub_file_entry,
2231 	                     ( (pyfsapfs_file_entry_t *) pyfsapfs_file_entry )->parent_object );
2232 
2233 	if( file_entry_object == NULL )
2234 	{
2235 		PyErr_Format(
2236 		 PyExc_MemoryError,
2237 		 "%s: unable to create sub file entry object.",
2238 		 function );
2239 
2240 		goto on_error;
2241 	}
2242 	return( file_entry_object );
2243 
2244 on_error:
2245 	if( sub_file_entry != NULL )
2246 	{
2247 		libfsapfs_file_entry_free(
2248 		 &sub_file_entry,
2249 		 NULL );
2250 	}
2251 	return( NULL );
2252 }
2253 
2254 /* Retrieves a specific of sub file entry
2255  * Returns a Python object if successful or NULL on error
2256  */
pyfsapfs_file_entry_get_sub_file_entry(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments,PyObject * keywords)2257 PyObject *pyfsapfs_file_entry_get_sub_file_entry(
2258            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
2259            PyObject *arguments,
2260            PyObject *keywords )
2261 {
2262 	PyObject *file_entry_object = NULL;
2263 	static char *keyword_list[] = { "sub_file_entry_index", NULL };
2264 	int sub_file_entry_index    = 0;
2265 
2266 	if( PyArg_ParseTupleAndKeywords(
2267 	     arguments,
2268 	     keywords,
2269 	     "i",
2270 	     keyword_list,
2271 	     &sub_file_entry_index ) == 0 )
2272 	{
2273 		return( NULL );
2274 	}
2275 	file_entry_object = pyfsapfs_file_entry_get_sub_file_entry_by_index(
2276 	                     (PyObject *) pyfsapfs_file_entry,
2277 	                     sub_file_entry_index );
2278 
2279 	return( file_entry_object );
2280 }
2281 
2282 /* Retrieves a sequence and iterator object for the sub file entries
2283  * Returns a Python object if successful or NULL on error
2284  */
pyfsapfs_file_entry_get_sub_file_entries(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)2285 PyObject *pyfsapfs_file_entry_get_sub_file_entries(
2286            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
2287            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
2288 {
2289 	PyObject *sequence_object      = NULL;
2290 	libcerror_error_t *error       = NULL;
2291 	static char *function          = "pyfsapfs_file_entry_get_sub_file_entries";
2292 	int number_of_sub_file_entries = 0;
2293 	int result                     = 0;
2294 
2295 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
2296 
2297 	if( pyfsapfs_file_entry == NULL )
2298 	{
2299 		PyErr_Format(
2300 		 PyExc_ValueError,
2301 		 "%s: invalid file entry.",
2302 		 function );
2303 
2304 		return( NULL );
2305 	}
2306 	Py_BEGIN_ALLOW_THREADS
2307 
2308 	result = libfsapfs_file_entry_get_number_of_sub_file_entries(
2309 	          pyfsapfs_file_entry->file_entry,
2310 	          &number_of_sub_file_entries,
2311 	          &error );
2312 
2313 	Py_END_ALLOW_THREADS
2314 
2315 	if( result != 1 )
2316 	{
2317 		pyfsapfs_error_raise(
2318 		 error,
2319 		 PyExc_IOError,
2320 		 "%s: unable to retrieve number of sub file entries.",
2321 		 function );
2322 
2323 		libcerror_error_free(
2324 		 &error );
2325 
2326 		return( NULL );
2327 	}
2328 	sequence_object = pyfsapfs_file_entries_new(
2329 	                   (PyObject *) pyfsapfs_file_entry,
2330 	                   &pyfsapfs_file_entry_get_sub_file_entry_by_index,
2331 	                   number_of_sub_file_entries );
2332 
2333 	if( sequence_object == NULL )
2334 	{
2335 		pyfsapfs_error_raise(
2336 		 error,
2337 		 PyExc_MemoryError,
2338 		 "%s: unable to create sequence object.",
2339 		 function );
2340 
2341 		return( NULL );
2342 	}
2343 	return( sequence_object );
2344 }
2345 
2346 /* Retrieves the sub  specified by the name
2347  * Returns a Python object if successful or NULL on error
2348  */
pyfsapfs_file_entry_get_sub_file_entry_by_name(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments,PyObject * keywords)2349 PyObject *pyfsapfs_file_entry_get_sub_file_entry_by_name(
2350            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
2351            PyObject *arguments,
2352            PyObject *keywords )
2353 {
2354 	PyObject *file_entry_object            = NULL;
2355 	libcerror_error_t *error               = NULL;
2356 	libfsapfs_file_entry_t *sub_file_entry = NULL;
2357 	static char *function                  = "pyfsapfs_file_entry_get_sub_file_entry_by_name";
2358 	static char *keyword_list[]            = { "name", NULL };
2359 	char *utf8_name                        = NULL;
2360 	size_t utf8_name_length                = 0;
2361 	int result                             = 0;
2362 
2363 	if( pyfsapfs_file_entry == NULL )
2364 	{
2365 		PyErr_Format(
2366 		 PyExc_ValueError,
2367 		 "%s: invalid file entry.",
2368 		 function );
2369 
2370 		return( NULL );
2371 	}
2372 	if( PyArg_ParseTupleAndKeywords(
2373 	     arguments,
2374 	     keywords,
2375 	     "s",
2376 	     keyword_list,
2377 	     &utf8_name ) == 0 )
2378 	{
2379 		goto on_error;
2380 	}
2381 	utf8_name_length = narrow_string_length(
2382 	                    utf8_name );
2383 
2384 	Py_BEGIN_ALLOW_THREADS
2385 
2386 	result = libfsapfs_file_entry_get_sub_file_entry_by_utf8_name(
2387 	          pyfsapfs_file_entry->file_entry,
2388 	          (uint8_t *) utf8_name,
2389 	          utf8_name_length,
2390 	          &sub_file_entry,
2391 	          &error );
2392 
2393 	Py_END_ALLOW_THREADS
2394 
2395 	if( result == -1 )
2396 	{
2397 		pyfsapfs_error_raise(
2398 		 error,
2399 		 PyExc_IOError,
2400 		 "%s: unable to retrieve sub .",
2401 		 function );
2402 
2403 		libcerror_error_free(
2404 		 &error );
2405 
2406 		goto on_error;
2407 	}
2408 	else if( result == 0 )
2409 	{
2410 		Py_IncRef(
2411 		 Py_None );
2412 
2413 		return( Py_None );
2414 	}
2415 	file_entry_object = pyfsapfs_file_entry_new(
2416 	                     sub_file_entry,
2417 	                     pyfsapfs_file_entry->parent_object );
2418 
2419 	if( file_entry_object == NULL )
2420 	{
2421 		PyErr_Format(
2422 		 PyExc_MemoryError,
2423 		 "%s: unable to create sub file entry object.",
2424 		 function );
2425 
2426 		goto on_error;
2427 	}
2428 	return( file_entry_object );
2429 
2430 on_error:
2431 	if( sub_file_entry != NULL )
2432 	{
2433 		libfsapfs_file_entry_free(
2434 		 &sub_file_entry,
2435 		 NULL );
2436 	}
2437 	return( NULL );
2438 }
2439 
2440 /* Reads data at the current offset into a buffer
2441  * Returns a Python object if successful or NULL on error
2442  */
pyfsapfs_file_entry_read_buffer(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments,PyObject * keywords)2443 PyObject *pyfsapfs_file_entry_read_buffer(
2444            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
2445            PyObject *arguments,
2446            PyObject *keywords )
2447 {
2448 	PyObject *integer_object    = NULL;
2449 	PyObject *string_object     = NULL;
2450 	libcerror_error_t *error    = NULL;
2451 	char *buffer                = NULL;
2452 	static char *function       = "pyfsapfs_file_entry_read_buffer";
2453 	static char *keyword_list[] = { "size", NULL };
2454 	ssize_t read_count          = 0;
2455 	int64_t read_size           = 0;
2456 	int result                  = 0;
2457 
2458 	if( pyfsapfs_file_entry == NULL )
2459 	{
2460 		PyErr_Format(
2461 		 PyExc_ValueError,
2462 		 "%s: invalid file entry.",
2463 		 function );
2464 
2465 		return( NULL );
2466 	}
2467 	if( PyArg_ParseTupleAndKeywords(
2468 	     arguments,
2469 	     keywords,
2470 	     "|O",
2471 	     keyword_list,
2472 	     &integer_object ) == 0 )
2473 	{
2474 		return( NULL );
2475 	}
2476 	if( integer_object == NULL )
2477 	{
2478 		result = 0;
2479 	}
2480 	else
2481 	{
2482 		result = PyObject_IsInstance(
2483 		          integer_object,
2484 		          (PyObject *) &PyLong_Type );
2485 
2486 		if( result == -1 )
2487 		{
2488 			pyfsapfs_error_fetch_and_raise(
2489 			 PyExc_RuntimeError,
2490 			 "%s: unable to determine if integer object is of type long.",
2491 			 function );
2492 
2493 			return( NULL );
2494 		}
2495 #if PY_MAJOR_VERSION < 3
2496 		else if( result == 0 )
2497 		{
2498 			PyErr_Clear();
2499 
2500 			result = PyObject_IsInstance(
2501 			          integer_object,
2502 			          (PyObject *) &PyInt_Type );
2503 
2504 			if( result == -1 )
2505 			{
2506 				pyfsapfs_error_fetch_and_raise(
2507 				 PyExc_RuntimeError,
2508 				 "%s: unable to determine if integer object is of type int.",
2509 				 function );
2510 
2511 				return( NULL );
2512 			}
2513 		}
2514 #endif
2515 	}
2516 	if( result != 0 )
2517 	{
2518 		if( pyfsapfs_integer_signed_copy_to_64bit(
2519 		     integer_object,
2520 		     &read_size,
2521 		     &error ) != 1 )
2522 		{
2523 			pyfsapfs_error_raise(
2524 			 error,
2525 			 PyExc_IOError,
2526 			 "%s: unable to convert integer object into read size.",
2527 			 function );
2528 
2529 			libcerror_error_free(
2530 			 &error );
2531 
2532 			return( NULL );
2533 		}
2534 	}
2535 	else if( ( integer_object == NULL )
2536 	      || ( integer_object == Py_None ) )
2537 	{
2538 		Py_BEGIN_ALLOW_THREADS
2539 
2540 		result = libfsapfs_file_entry_get_size(
2541 		          pyfsapfs_file_entry->file_entry,
2542 		          (size64_t *) &read_size,
2543 		          &error );
2544 
2545 		Py_END_ALLOW_THREADS
2546 
2547 		if( result != 1 )
2548 		{
2549 			pyfsapfs_error_raise(
2550 			 error,
2551 			 PyExc_IOError,
2552 			 "%s: unable to retrieve size.",
2553 			 function );
2554 
2555 			libcerror_error_free(
2556 			 &error );
2557 
2558 			return( NULL );
2559 		}
2560 	}
2561 	else
2562 	{
2563 		PyErr_Format(
2564 		 PyExc_TypeError,
2565 		 "%s: unsupported integer object type.",
2566 		 function );
2567 
2568 		return( NULL );
2569 	}
2570 	if( read_size == 0 )
2571 	{
2572 #if PY_MAJOR_VERSION >= 3
2573 		string_object = PyBytes_FromString(
2574 		                 "" );
2575 #else
2576 		string_object = PyString_FromString(
2577 		                 "" );
2578 #endif
2579 		return( string_object );
2580 	}
2581 	if( read_size < 0 )
2582 	{
2583 		PyErr_Format(
2584 		 PyExc_ValueError,
2585 		 "%s: invalid read size value less than zero.",
2586 		 function );
2587 
2588 		return( NULL );
2589 	}
2590 	/* Make sure the data fits into a memory buffer
2591 	 */
2592 	if( ( read_size > (int64_t) INT_MAX )
2593 	 || ( read_size > (int64_t) SSIZE_MAX ) )
2594 	{
2595 		PyErr_Format(
2596 		 PyExc_ValueError,
2597 		 "%s: invalid argument read size value exceeds maximum.",
2598 		 function );
2599 
2600 		return( NULL );
2601 	}
2602 #if PY_MAJOR_VERSION >= 3
2603 	string_object = PyBytes_FromStringAndSize(
2604 	                 NULL,
2605 	                 (Py_ssize_t) read_size );
2606 
2607 	buffer = PyBytes_AsString(
2608 	          string_object );
2609 #else
2610 	/* Note that a size of 0 is not supported
2611 	 */
2612 	string_object = PyString_FromStringAndSize(
2613 	                 NULL,
2614 	                 (Py_ssize_t) read_size );
2615 
2616 	buffer = PyString_AsString(
2617 	          string_object );
2618 #endif
2619 	Py_BEGIN_ALLOW_THREADS
2620 
2621 	read_count = libfsapfs_file_entry_read_buffer(
2622 	              pyfsapfs_file_entry->file_entry,
2623 	              (uint8_t *) buffer,
2624 	              (size_t) read_size,
2625 	              &error );
2626 
2627 	Py_END_ALLOW_THREADS
2628 
2629 	if( read_count == -1 )
2630 	{
2631 		pyfsapfs_error_raise(
2632 		 error,
2633 		 PyExc_IOError,
2634 		 "%s: unable to read data.",
2635 		 function );
2636 
2637 		libcerror_error_free(
2638 		 &error );
2639 
2640 		Py_DecRef(
2641 		 (PyObject *) string_object );
2642 
2643 		return( NULL );
2644 	}
2645 	/* Need to resize the string here in case read_size was not fully read.
2646 	 */
2647 #if PY_MAJOR_VERSION >= 3
2648 	if( _PyBytes_Resize(
2649 	     &string_object,
2650 	     (Py_ssize_t) read_count ) != 0 )
2651 #else
2652 	if( _PyString_Resize(
2653 	     &string_object,
2654 	     (Py_ssize_t) read_count ) != 0 )
2655 #endif
2656 	{
2657 		Py_DecRef(
2658 		 (PyObject *) string_object );
2659 
2660 		return( NULL );
2661 	}
2662 	return( string_object );
2663 }
2664 
2665 /* Reads data at a specific offset into a buffer
2666  * Returns a Python object if successful or NULL on error
2667  */
pyfsapfs_file_entry_read_buffer_at_offset(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments,PyObject * keywords)2668 PyObject *pyfsapfs_file_entry_read_buffer_at_offset(
2669            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
2670            PyObject *arguments,
2671            PyObject *keywords )
2672 {
2673 	PyObject *integer_object    = NULL;
2674 	PyObject *string_object     = NULL;
2675 	libcerror_error_t *error    = NULL;
2676 	char *buffer                = NULL;
2677 	static char *function       = "pyfsapfs_file_entry_read_buffer_at_offset";
2678 	static char *keyword_list[] = { "size", "offset", NULL };
2679 	ssize_t read_count          = 0;
2680 	off64_t read_offset         = 0;
2681 	int64_t read_size           = 0;
2682 	int result                  = 0;
2683 
2684 	if( pyfsapfs_file_entry == NULL )
2685 	{
2686 		PyErr_Format(
2687 		 PyExc_ValueError,
2688 		 "%s: invalid file entry.",
2689 		 function );
2690 
2691 		return( NULL );
2692 	}
2693 	if( PyArg_ParseTupleAndKeywords(
2694 	     arguments,
2695 	     keywords,
2696 	     "OL",
2697 	     keyword_list,
2698 	     &integer_object,
2699 	     &read_offset ) == 0 )
2700 	{
2701 		return( NULL );
2702 	}
2703 	result = PyObject_IsInstance(
2704 	          integer_object,
2705 	          (PyObject *) &PyLong_Type );
2706 
2707 	if( result == -1 )
2708 	{
2709 		pyfsapfs_error_fetch_and_raise(
2710 		 PyExc_RuntimeError,
2711 		 "%s: unable to determine if integer object is of type long.",
2712 		 function );
2713 
2714 		return( NULL );
2715 	}
2716 #if PY_MAJOR_VERSION < 3
2717 	else if( result == 0 )
2718 	{
2719 		PyErr_Clear();
2720 
2721 		result = PyObject_IsInstance(
2722 		          integer_object,
2723 		          (PyObject *) &PyInt_Type );
2724 
2725 		if( result == -1 )
2726 		{
2727 			pyfsapfs_error_fetch_and_raise(
2728 			 PyExc_RuntimeError,
2729 			 "%s: unable to determine if integer object is of type int.",
2730 			 function );
2731 
2732 			return( NULL );
2733 		}
2734 	}
2735 #endif
2736 	if( result != 0 )
2737 	{
2738 		if( pyfsapfs_integer_signed_copy_to_64bit(
2739 		     integer_object,
2740 		     &read_size,
2741 		     &error ) != 1 )
2742 		{
2743 			pyfsapfs_error_raise(
2744 			 error,
2745 			 PyExc_IOError,
2746 			 "%s: unable to convert integer object into read size.",
2747 			 function );
2748 
2749 			libcerror_error_free(
2750 			 &error );
2751 
2752 			return( NULL );
2753 		}
2754 	}
2755 	else
2756 	{
2757 		PyErr_Format(
2758 		 PyExc_TypeError,
2759 		 "%s: unsupported integer object type.",
2760 		 function );
2761 
2762 		return( NULL );
2763 	}
2764 	if( read_size == 0 )
2765 	{
2766 #if PY_MAJOR_VERSION >= 3
2767 		string_object = PyBytes_FromString(
2768 		                 "" );
2769 #else
2770 		string_object = PyString_FromString(
2771 		                 "" );
2772 #endif
2773 		return( string_object );
2774 	}
2775 	if( read_size < 0 )
2776 	{
2777 		PyErr_Format(
2778 		 PyExc_ValueError,
2779 		 "%s: invalid read size value less than zero.",
2780 		 function );
2781 
2782 		return( NULL );
2783 	}
2784 	/* Make sure the data fits into a memory buffer
2785 	 */
2786 	if( ( read_size > (int64_t) INT_MAX )
2787 	 || ( read_size > (int64_t) SSIZE_MAX ) )
2788 	{
2789 		PyErr_Format(
2790 		 PyExc_ValueError,
2791 		 "%s: invalid argument read size value exceeds maximum.",
2792 		 function );
2793 
2794 		return( NULL );
2795 	}
2796 	if( read_offset < 0 )
2797 	{
2798 		PyErr_Format(
2799 		 PyExc_ValueError,
2800 		 "%s: invalid read offset value less than zero.",
2801 		 function );
2802 
2803 		return( NULL );
2804 	}
2805 #if PY_MAJOR_VERSION >= 3
2806 	string_object = PyBytes_FromStringAndSize(
2807 	                 NULL,
2808 	                 (Py_ssize_t) read_size );
2809 
2810 	buffer = PyBytes_AsString(
2811 	          string_object );
2812 #else
2813 	/* Note that a size of 0 is not supported
2814 	 */
2815 	string_object = PyString_FromStringAndSize(
2816 	                 NULL,
2817 	                 (Py_ssize_t) read_size );
2818 
2819 	buffer = PyString_AsString(
2820 	          string_object );
2821 #endif
2822 	Py_BEGIN_ALLOW_THREADS
2823 
2824 	read_count = libfsapfs_file_entry_read_buffer_at_offset(
2825 	              pyfsapfs_file_entry->file_entry,
2826 	              (uint8_t *) buffer,
2827 	              (size_t) read_size,
2828 	              (off64_t) read_offset,
2829 	              &error );
2830 
2831 	Py_END_ALLOW_THREADS
2832 
2833 	if( read_count == -1 )
2834 	{
2835 		pyfsapfs_error_raise(
2836 		 error,
2837 		 PyExc_IOError,
2838 		 "%s: unable to read data.",
2839 		 function );
2840 
2841 		libcerror_error_free(
2842 		 &error );
2843 
2844 		Py_DecRef(
2845 		 (PyObject *) string_object );
2846 
2847 		return( NULL );
2848 	}
2849 	/* Need to resize the string here in case read_size was not fully read.
2850 	 */
2851 #if PY_MAJOR_VERSION >= 3
2852 	if( _PyBytes_Resize(
2853 	     &string_object,
2854 	     (Py_ssize_t) read_count ) != 0 )
2855 #else
2856 	if( _PyString_Resize(
2857 	     &string_object,
2858 	     (Py_ssize_t) read_count ) != 0 )
2859 #endif
2860 	{
2861 		Py_DecRef(
2862 		 (PyObject *) string_object );
2863 
2864 		return( NULL );
2865 	}
2866 	return( string_object );
2867 }
2868 
2869 /* Seeks a certain offset
2870  * Returns a Python object if successful or NULL on error
2871  */
pyfsapfs_file_entry_seek_offset(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments,PyObject * keywords)2872 PyObject *pyfsapfs_file_entry_seek_offset(
2873            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
2874            PyObject *arguments,
2875            PyObject *keywords )
2876 {
2877 	libcerror_error_t *error    = NULL;
2878 	static char *function       = "pyfsapfs_file_entry_seek_offset";
2879 	static char *keyword_list[] = { "offset", "whence", NULL };
2880 	off64_t offset              = 0;
2881 	int whence                  = 0;
2882 
2883 	if( pyfsapfs_file_entry == NULL )
2884 	{
2885 		PyErr_Format(
2886 		 PyExc_ValueError,
2887 		 "%s: invalid file entry.",
2888 		 function );
2889 
2890 		return( NULL );
2891 	}
2892 	if( PyArg_ParseTupleAndKeywords(
2893 	     arguments,
2894 	     keywords,
2895 	     "L|i",
2896 	     keyword_list,
2897 	     &offset,
2898 	     &whence ) == 0 )
2899 	{
2900 		return( NULL );
2901 	}
2902 	Py_BEGIN_ALLOW_THREADS
2903 
2904 	offset = libfsapfs_file_entry_seek_offset(
2905 	          pyfsapfs_file_entry->file_entry,
2906 	          offset,
2907 	          whence,
2908 	          &error );
2909 
2910 	Py_END_ALLOW_THREADS
2911 
2912  	if( offset == -1 )
2913 	{
2914 		pyfsapfs_error_raise(
2915 		 error,
2916 		 PyExc_IOError,
2917 		 "%s: unable to seek offset.",
2918 		 function );
2919 
2920 		libcerror_error_free(
2921 		 &error );
2922 
2923 		return( NULL );
2924 	}
2925 	Py_IncRef(
2926 	 Py_None );
2927 
2928 	return( Py_None );
2929 }
2930 
2931 /* Retrieves the current offset
2932  * Returns a Python object if successful or NULL on error
2933  */
pyfsapfs_file_entry_get_offset(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)2934 PyObject *pyfsapfs_file_entry_get_offset(
2935            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
2936            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
2937 {
2938 	PyObject *integer_object = NULL;
2939 	libcerror_error_t *error = NULL;
2940 	static char *function    = "pyfsapfs_file_entry_get_offset";
2941 	off64_t offset           = 0;
2942 	int result               = 0;
2943 
2944 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
2945 
2946 	if( pyfsapfs_file_entry == NULL )
2947 	{
2948 		PyErr_Format(
2949 		 PyExc_ValueError,
2950 		 "%s: invalid file entry.",
2951 		 function );
2952 
2953 		return( NULL );
2954 	}
2955 	Py_BEGIN_ALLOW_THREADS
2956 
2957 	result = libfsapfs_file_entry_get_offset(
2958 	          pyfsapfs_file_entry->file_entry,
2959 	          &offset,
2960 	          &error );
2961 
2962 	Py_END_ALLOW_THREADS
2963 
2964 	if( result == -1 )
2965 	{
2966 		pyfsapfs_error_raise(
2967 		 error,
2968 		 PyExc_IOError,
2969 		 "%s: unable to retrieve .",
2970 		 function );
2971 
2972 		libcerror_error_free(
2973 		 &error );
2974 
2975 		return( NULL );
2976 	}
2977 	else if( result == 0 )
2978 	{
2979 		Py_IncRef(
2980 		 Py_None );
2981 
2982 		return( Py_None );
2983 	}
2984 	integer_object = pyfsapfs_integer_signed_new_from_64bit(
2985 	                  (int64_t) offset );
2986 
2987 	return( integer_object );
2988 }
2989 
2990 /* Retrieves the size
2991  * Returns a Python object if successful or NULL on error
2992  */
pyfsapfs_file_entry_get_size(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)2993 PyObject *pyfsapfs_file_entry_get_size(
2994            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
2995            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
2996 {
2997 	PyObject *integer_object = NULL;
2998 	libcerror_error_t *error = NULL;
2999 	static char *function    = "pyfsapfs_file_entry_get_size";
3000 	size64_t size            = 0;
3001 	int result               = 0;
3002 
3003 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
3004 
3005 	if( pyfsapfs_file_entry == NULL )
3006 	{
3007 		PyErr_Format(
3008 		 PyExc_ValueError,
3009 		 "%s: invalid file entry.",
3010 		 function );
3011 
3012 		return( NULL );
3013 	}
3014 	Py_BEGIN_ALLOW_THREADS
3015 
3016 	result = libfsapfs_file_entry_get_size(
3017 	          pyfsapfs_file_entry->file_entry,
3018 	          &size,
3019 	          &error );
3020 
3021 	Py_END_ALLOW_THREADS
3022 
3023 	if( result != 1 )
3024 	{
3025 		pyfsapfs_error_raise(
3026 		 error,
3027 		 PyExc_IOError,
3028 		 "%s: failed to retrieve .",
3029 		 function );
3030 
3031 		libcerror_error_free(
3032 		 &error );
3033 
3034 		return( NULL );
3035 	}
3036 	integer_object = pyfsapfs_integer_unsigned_new_from_64bit(
3037 	                  (uint64_t) size );
3038 
3039 	return( integer_object );
3040 }
3041 
3042 /* Retrieves the number of extents
3043  * Returns a Python object if successful or NULL on error
3044  */
pyfsapfs_file_entry_get_number_of_extents(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments PYFSAPFS_ATTRIBUTE_UNUSED)3045 PyObject *pyfsapfs_file_entry_get_number_of_extents(
3046            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
3047            PyObject *arguments PYFSAPFS_ATTRIBUTE_UNUSED )
3048 {
3049 	PyObject *integer_object = NULL;
3050 	libcerror_error_t *error = NULL;
3051 	static char *function    = "pyfsapfs_file_entry_get_number_of_extents";
3052 	int number_of_extents    = 0;
3053 	int result               = 0;
3054 
3055 	PYFSAPFS_UNREFERENCED_PARAMETER( arguments )
3056 
3057 	if( pyfsapfs_file_entry == NULL )
3058 	{
3059 		PyErr_Format(
3060 		 PyExc_ValueError,
3061 		 "%s: invalid file entry.",
3062 		 function );
3063 
3064 		return( NULL );
3065 	}
3066 	Py_BEGIN_ALLOW_THREADS
3067 
3068 	result = libfsapfs_file_entry_get_number_of_extents(
3069 	          pyfsapfs_file_entry->file_entry,
3070 	          &number_of_extents,
3071 	          &error );
3072 
3073 	Py_END_ALLOW_THREADS
3074 
3075 	if( result != 1 )
3076 	{
3077 		pyfsapfs_error_raise(
3078 		 error,
3079 		 PyExc_IOError,
3080 		 "%s: unable to retrieve .",
3081 		 function );
3082 
3083 		libcerror_error_free(
3084 		 &error );
3085 
3086 		return( NULL );
3087 	}
3088 #if PY_MAJOR_VERSION >= 3
3089 	integer_object = PyLong_FromLong(
3090 	                  (long) number_of_extents );
3091 #else
3092 	integer_object = PyInt_FromLong(
3093 	                  (long) number_of_extents );
3094 #endif
3095 	return( integer_object );
3096 }
3097 
3098 /* Retrieves a specific extent by index
3099  * Returns a Python object if successful or NULL on error
3100  */
pyfsapfs_file_entry_get_extent_by_index(pyfsapfs_file_entry_t * pyfsapfs_file_entry,int extent_index)3101 PyObject *pyfsapfs_file_entry_get_extent_by_index(
3102            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
3103            int extent_index )
3104 {
3105 	libcerror_error_t *error = NULL;
3106 	PyObject *integer_object = NULL;
3107 	PyObject *tuple_object   = NULL;
3108 	static char *function    = "pyfsapfs_file_entry_get_extent_by_index";
3109 	off64_t extent_offset    = 0;
3110 	size64_t extent_size     = 0;
3111 	uint32_t extent_flags    = 0;
3112 	int result               = 0;
3113 
3114 	if( pyfsapfs_file_entry == NULL )
3115 	{
3116 		PyErr_Format(
3117 		 PyExc_TypeError,
3118 		 "%s: invalid file entry.",
3119 		 function );
3120 
3121 		return( NULL );
3122 	}
3123 	Py_BEGIN_ALLOW_THREADS
3124 
3125 	result = libfsapfs_file_entry_get_extent_by_index(
3126 	          pyfsapfs_file_entry->file_entry,
3127 	          extent_index,
3128 	          &extent_offset,
3129 	          &extent_size,
3130 	          &extent_flags,
3131 	          &error );
3132 
3133 	Py_END_ALLOW_THREADS
3134 
3135 	if( result != 1 )
3136 	{
3137 		pyfsapfs_error_raise(
3138 		 error,
3139 		 PyExc_IOError,
3140 		 "%s: unable to retrieve extent: %d.",
3141 		 function,
3142 		 extent_index );
3143 
3144 		libcerror_error_free(
3145 		 &error );
3146 
3147 		goto on_error;
3148 	}
3149 	tuple_object = PyTuple_New(
3150                         3 );
3151 
3152 	integer_object = pyfsapfs_integer_signed_new_from_64bit(
3153 	                  (int64_t) extent_offset );
3154 
3155 	/* Tuple set item does not increment the reference count of the integer object
3156 	 */
3157 	if( PyTuple_SetItem(
3158 	     tuple_object,
3159 	     0,
3160 	     integer_object ) != 0 )
3161 	{
3162 		goto on_error;
3163 	}
3164 	integer_object = pyfsapfs_integer_unsigned_new_from_64bit(
3165 	                  (uint64_t) extent_size );
3166 
3167 	/* Tuple set item does not increment the reference count of the integer object
3168 	 */
3169 	if( PyTuple_SetItem(
3170 	     tuple_object,
3171 	     1,
3172 	     integer_object ) != 0 )
3173 	{
3174 		goto on_error;
3175 	}
3176 	integer_object = pyfsapfs_integer_unsigned_new_from_64bit(
3177 	                  (uint64_t) extent_flags );
3178 
3179 	/* Tuple set item does not increment the reference count of the integer object
3180 	 */
3181 	if( PyTuple_SetItem(
3182 	     tuple_object,
3183 	     2,
3184 	     integer_object ) != 0 )
3185 	{
3186 		goto on_error;
3187 	}
3188 	return( tuple_object );
3189 
3190 on_error:
3191 	if( integer_object != NULL )
3192 	{
3193 		Py_DecRef(
3194 		 (PyObject *) integer_object );
3195 	}
3196 	if( tuple_object != NULL )
3197 	{
3198 		Py_DecRef(
3199 		 (PyObject *) tuple_object );
3200 	}
3201 	return( NULL );
3202 }
3203 
3204 /* Retrieves a specific extent
3205  * Returns a Python object if successful or NULL on error
3206  */
pyfsapfs_file_entry_get_extent(pyfsapfs_file_entry_t * pyfsapfs_file_entry,PyObject * arguments,PyObject * keywords)3207 PyObject *pyfsapfs_file_entry_get_extent(
3208            pyfsapfs_file_entry_t *pyfsapfs_file_entry,
3209            PyObject *arguments,
3210            PyObject *keywords )
3211 {
3212 	PyObject *sequence_object   = NULL;
3213 	static char *keyword_list[] = { "extent_index", NULL };
3214 	int extent_index            = 0;
3215 
3216 	if( PyArg_ParseTupleAndKeywords(
3217 	     arguments,
3218 	     keywords,
3219 	     "i",
3220 	     keyword_list,
3221 	     &extent_index ) == 0 )
3222 	{
3223 		return( NULL );
3224 	}
3225 	sequence_object = pyfsapfs_file_entry_get_extent_by_index(
3226 	                   pyfsapfs_file_entry,
3227 	                   extent_index );
3228 
3229 	return( sequence_object );
3230 }
3231 
3232