1 /*
2  * Inode functions
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 <byte_stream.h>
24 #include <memory.h>
25 #include <types.h>
26 
27 #include "libfsapfs_debug.h"
28 #include "libfsapfs_inode.h"
29 #include "libfsapfs_libcerror.h"
30 #include "libfsapfs_libcnotify.h"
31 #include "libfsapfs_libfdatetime.h"
32 #include "libfsapfs_libuna.h"
33 
34 #include "fsapfs_file_system.h"
35 
36 /* Creates a inode
37  * Make sure the value inode is referencing, is set to NULL
38  * Returns 1 if successful or -1 on error
39  */
libfsapfs_inode_initialize(libfsapfs_inode_t ** inode,libcerror_error_t ** error)40 int libfsapfs_inode_initialize(
41      libfsapfs_inode_t **inode,
42      libcerror_error_t **error )
43 {
44 	static char *function = "libfsapfs_inode_initialize";
45 
46 	if( inode == NULL )
47 	{
48 		libcerror_error_set(
49 		 error,
50 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52 		 "%s: invalid inode.",
53 		 function );
54 
55 		return( -1 );
56 	}
57 	if( *inode != NULL )
58 	{
59 		libcerror_error_set(
60 		 error,
61 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
62 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63 		 "%s: invalid inode value already set.",
64 		 function );
65 
66 		return( -1 );
67 	}
68 	*inode = memory_allocate_structure(
69 	          libfsapfs_inode_t );
70 
71 	if( *inode == NULL )
72 	{
73 		libcerror_error_set(
74 		 error,
75 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
76 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
77 		 "%s: unable to create inode.",
78 		 function );
79 
80 		goto on_error;
81 	}
82 	if( memory_set(
83 	     *inode,
84 	     0,
85 	     sizeof( libfsapfs_inode_t ) ) == NULL )
86 	{
87 		libcerror_error_set(
88 		 error,
89 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
90 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
91 		 "%s: unable to clear inode.",
92 		 function );
93 
94 		goto on_error;
95 	}
96 	return( 1 );
97 
98 on_error:
99 	if( *inode != NULL )
100 	{
101 		memory_free(
102 		 *inode );
103 
104 		*inode = NULL;
105 	}
106 	return( -1 );
107 }
108 
109 /* Frees a inode
110  * Returns 1 if successful or -1 on error
111  */
libfsapfs_inode_free(libfsapfs_inode_t ** inode,libcerror_error_t ** error)112 int libfsapfs_inode_free(
113      libfsapfs_inode_t **inode,
114      libcerror_error_t **error )
115 {
116 	static char *function = "libfsapfs_inode_free";
117 
118 	if( inode == NULL )
119 	{
120 		libcerror_error_set(
121 		 error,
122 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
123 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
124 		 "%s: invalid inode.",
125 		 function );
126 
127 		return( -1 );
128 	}
129 	if( *inode != NULL )
130 	{
131 		if( ( *inode )->name != NULL )
132 		{
133 			memory_free(
134 			 ( *inode )->name );
135 		}
136 		memory_free(
137 		 *inode );
138 
139 		*inode = NULL;
140 	}
141 	return( 1 );
142 }
143 
144 /* Reads the inode key data
145  * Returns 1 if successful or -1 on error
146  */
libfsapfs_inode_read_key_data(libfsapfs_inode_t * inode,const uint8_t * data,size_t data_size,libcerror_error_t ** error)147 int libfsapfs_inode_read_key_data(
148      libfsapfs_inode_t *inode,
149      const uint8_t *data,
150      size_t data_size,
151      libcerror_error_t **error )
152 {
153 	static char *function = "libfsapfs_inode_read_key_data";
154 
155 	if( inode == NULL )
156 	{
157 		libcerror_error_set(
158 		 error,
159 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
160 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
161 		 "%s: invalid inode.",
162 		 function );
163 
164 		return( -1 );
165 	}
166 	if( data == NULL )
167 	{
168 		libcerror_error_set(
169 		 error,
170 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
171 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
172 		 "%s: invalid data.",
173 		 function );
174 
175 		return( -1 );
176 	}
177 	if( ( data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
178 	 || ( data_size > (size_t) SSIZE_MAX ) )
179 	{
180 		libcerror_error_set(
181 		 error,
182 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
183 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
184 		 "%s: invalid data size value out of bounds.",
185 		 function );
186 
187 		return( -1 );
188 	}
189 #if defined( HAVE_DEBUG_OUTPUT )
190 	if( libcnotify_verbose != 0 )
191 	{
192 		libcnotify_printf(
193 		 "%s: inode key data:\n",
194 		 function );
195 		libcnotify_print_data(
196 		 data,
197 		 data_size,
198 		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
199 	}
200 #endif
201 	byte_stream_copy_to_uint64_little_endian(
202 	 ( (fsapfs_file_system_btree_key_common_t *) data )->file_system_identifier,
203 	 inode->identifier );
204 
205 #if defined( HAVE_DEBUG_OUTPUT )
206 	if( libcnotify_verbose != 0 )
207 	{
208 		libcnotify_printf(
209 		 "%s: identifier\t\t\t\t: 0x%08" PRIx64 "\n",
210 		 function,
211 		 inode->identifier );
212 
213 		libcnotify_printf(
214 		 "\n" );
215 	}
216 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
217 
218 	inode->identifier &= (uint64_t) 0x0fffffffffffffffUL;
219 
220 	return( 1 );
221 }
222 
223 /* Reads the inode value data
224  * Returns 1 if successful or -1 on error
225  */
libfsapfs_inode_read_value_data(libfsapfs_inode_t * inode,const uint8_t * data,size_t data_size,libcerror_error_t ** error)226 int libfsapfs_inode_read_value_data(
227      libfsapfs_inode_t *inode,
228      const uint8_t *data,
229      size_t data_size,
230      libcerror_error_t **error )
231 {
232 	const uint8_t *value_data          = NULL;
233 	static char *function              = "libfsapfs_inode_read_value_data";
234 	size_t data_offset                 = 0;
235 	size_t trailing_data_size          = 0;
236 	size_t value_data_offset           = 0;
237 	uint16_t extended_field_index      = 0;
238 	uint16_t number_of_extended_fields = 0;
239 	uint16_t value_data_size           = 0;
240 	uint8_t extended_field_flags       = 0;
241 	uint8_t extended_field_type        = 0;
242 
243 #if defined( HAVE_DEBUG_OUTPUT )
244 	uint64_t value_64bit               = 0;
245 	uint32_t value_32bit               = 0;
246 	uint16_t value_16bit               = 0;
247 #endif
248 
249 	if( inode == NULL )
250 	{
251 		libcerror_error_set(
252 		 error,
253 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
254 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
255 		 "%s: invalid inode.",
256 		 function );
257 
258 		return( -1 );
259 	}
260 	if( inode->name != NULL )
261 	{
262 		libcerror_error_set(
263 		 error,
264 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
265 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
266 		 "%s: invalid inode - name value already set.",
267 		 function );
268 
269 		return( -1 );
270 	}
271 	if( data == NULL )
272 	{
273 		libcerror_error_set(
274 		 error,
275 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
276 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
277 		 "%s: invalid data.",
278 		 function );
279 
280 		return( -1 );
281 	}
282 	if( ( data_size < sizeof( fsapfs_file_system_btree_value_inode_t ) )
283 	 || ( data_size > (size_t) SSIZE_MAX ) )
284 	{
285 		libcerror_error_set(
286 		 error,
287 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
288 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
289 		 "%s: invalid data size value out of bounds.",
290 		 function );
291 
292 		return( -1 );
293 	}
294 #if defined( HAVE_DEBUG_OUTPUT )
295 	if( libcnotify_verbose != 0 )
296 	{
297 		libcnotify_printf(
298 		 "%s: inode value data:\n",
299 		 function );
300 		libcnotify_print_data(
301 		 data,
302 		 data_size,
303 		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
304 	}
305 #endif
306 	byte_stream_copy_to_uint64_little_endian(
307 	 ( (fsapfs_file_system_btree_value_inode_t *) data )->parent_identifier,
308 	 inode->parent_identifier );
309 
310 	byte_stream_copy_to_uint64_little_endian(
311 	 ( (fsapfs_file_system_btree_value_inode_t *) data )->data_stream_identifier,
312 	 inode->data_stream_identifier );
313 
314 	byte_stream_copy_to_uint64_little_endian(
315 	 ( (fsapfs_file_system_btree_value_inode_t *) data )->modification_time,
316 	 inode->modification_time );
317 
318 	byte_stream_copy_to_uint64_little_endian(
319 	 ( (fsapfs_file_system_btree_value_inode_t *) data )->creation_time,
320 	 inode->creation_time );
321 
322 	byte_stream_copy_to_uint64_little_endian(
323 	 ( (fsapfs_file_system_btree_value_inode_t *) data )->inode_change_time,
324 	 inode->inode_change_time );
325 
326 	byte_stream_copy_to_uint64_little_endian(
327 	 ( (fsapfs_file_system_btree_value_inode_t *) data )->access_time,
328 	 inode->access_time );
329 
330 	byte_stream_copy_to_uint64_little_endian(
331 	 ( (fsapfs_file_system_btree_value_inode_t *) data )->inode_flags,
332 	 inode->flags );
333 
334 	byte_stream_copy_to_uint32_little_endian(
335 	 ( (fsapfs_file_system_btree_value_inode_t *) data )->owner_identifier,
336 	 inode->owner_identifier );
337 
338 	byte_stream_copy_to_uint32_little_endian(
339 	 ( (fsapfs_file_system_btree_value_inode_t *) data )->group_identifier,
340 	 inode->group_identifier );
341 
342 	byte_stream_copy_to_uint16_little_endian(
343 	 ( (fsapfs_file_system_btree_value_inode_t *) data )->file_mode,
344 	 inode->file_mode );
345 
346 #if defined( HAVE_DEBUG_OUTPUT )
347 	if( libcnotify_verbose != 0 )
348 	{
349 		libcnotify_printf(
350 		 "%s: parent identifier\t\t\t: %" PRIu64 "\n",
351 		 function,
352 		 inode->parent_identifier );
353 
354 		libcnotify_printf(
355 		 "%s: data stream identifier\t\t\t: %" PRIu64 "\n",
356 		 function,
357 		 inode->data_stream_identifier );
358 
359 		if( libfsapfs_debug_print_posix_time_value(
360 		     function,
361 		     "modification time\t\t\t",
362 		     ( (fsapfs_file_system_btree_value_inode_t *) data )->modification_time,
363 		     8,
364 		     LIBFDATETIME_ENDIAN_LITTLE,
365 		     LIBFDATETIME_POSIX_TIME_VALUE_TYPE_NANO_SECONDS_64BIT_SIGNED,
366 		     LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
367 		     error ) != 1 )
368 		{
369 			libcerror_error_set(
370 			 error,
371 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
372 			 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
373 			 "%s: unable to print POSIX time value.",
374 			 function );
375 
376 			goto on_error;
377 		}
378 		if( libfsapfs_debug_print_posix_time_value(
379 		     function,
380 		     "creation time\t\t\t\t",
381 		     ( (fsapfs_file_system_btree_value_inode_t *) data )->creation_time,
382 		     8,
383 		     LIBFDATETIME_ENDIAN_LITTLE,
384 		     LIBFDATETIME_POSIX_TIME_VALUE_TYPE_NANO_SECONDS_64BIT_SIGNED,
385 		     LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
386 		     error ) != 1 )
387 		{
388 			libcerror_error_set(
389 			 error,
390 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
391 			 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
392 			 "%s: unable to print POSIX time value.",
393 			 function );
394 
395 			goto on_error;
396 		}
397 		if( libfsapfs_debug_print_posix_time_value(
398 		     function,
399 		     "inode change time\t\t\t",
400 		     ( (fsapfs_file_system_btree_value_inode_t *) data )->inode_change_time,
401 		     8,
402 		     LIBFDATETIME_ENDIAN_LITTLE,
403 		     LIBFDATETIME_POSIX_TIME_VALUE_TYPE_NANO_SECONDS_64BIT_SIGNED,
404 		     LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
405 		     error ) != 1 )
406 		{
407 			libcerror_error_set(
408 			 error,
409 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
410 			 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
411 			 "%s: unable to print POSIX time value.",
412 			 function );
413 
414 			goto on_error;
415 		}
416 		if( libfsapfs_debug_print_posix_time_value(
417 		     function,
418 		     "access time\t\t\t\t",
419 		     ( (fsapfs_file_system_btree_value_inode_t *) data )->access_time,
420 		     8,
421 		     LIBFDATETIME_ENDIAN_LITTLE,
422 		     LIBFDATETIME_POSIX_TIME_VALUE_TYPE_NANO_SECONDS_64BIT_SIGNED,
423 		     LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
424 		     error ) != 1 )
425 		{
426 			libcerror_error_set(
427 			 error,
428 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
429 			 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
430 			 "%s: unable to print POSIX time value.",
431 			 function );
432 
433 			goto on_error;
434 		}
435 		libcnotify_printf(
436 		 "%s: inode flags\t\t\t\t: 0x%08" PRIx64 "\n",
437 		 function,
438 		 inode->flags );
439 		libfsapfs_debug_print_inode_flags(
440 		 inode->flags );
441 		libcnotify_printf(
442 		 "\n" );
443 
444 		byte_stream_copy_to_uint32_little_endian(
445 		 ( (fsapfs_file_system_btree_value_inode_t *) data )->number_of_children,
446 		 value_32bit );
447 		libcnotify_printf(
448 		 "%s: number of children\t\t\t: %" PRIu32 "\n",
449 		 function,
450 		 value_32bit );
451 
452 		byte_stream_copy_to_uint32_little_endian(
453 		 ( (fsapfs_file_system_btree_value_inode_t *) data )->unknown1,
454 		 value_32bit );
455 		libcnotify_printf(
456 		 "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n",
457 		 function,
458 		 value_32bit );
459 
460 		byte_stream_copy_to_uint32_little_endian(
461 		 ( (fsapfs_file_system_btree_value_inode_t *) data )->unknown2,
462 		 value_32bit );
463 		libcnotify_printf(
464 		 "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n",
465 		 function,
466 		 value_32bit );
467 
468 		byte_stream_copy_to_uint32_little_endian(
469 		 ( (fsapfs_file_system_btree_value_inode_t *) data )->bsd_flags,
470 		 value_32bit );
471 		libcnotify_printf(
472 		 "%s: BSD flags\t\t\t\t: 0x%08" PRIx32 "\n",
473 		 function,
474 		 value_32bit );
475 
476 		libcnotify_printf(
477 		 "%s: owner identifier\t\t\t: %" PRIu32 "\n",
478 		 function,
479 		 inode->owner_identifier );
480 
481 		libcnotify_printf(
482 		 "%s: group identifier\t\t\t: %" PRIu32 "\n",
483 		 function,
484 		 inode->group_identifier );
485 
486 		libcnotify_printf(
487 		 "%s: file mode\t\t\t\t: %" PRIo16 "\n",
488 		 function,
489 		 inode->file_mode );
490 
491 		byte_stream_copy_to_uint16_little_endian(
492 		 ( (fsapfs_file_system_btree_value_inode_t *) data )->unknown3,
493 		 value_16bit );
494 		libcnotify_printf(
495 		 "%s: unknown3\t\t\t\t: 0x%04" PRIx16 "\n",
496 		 function,
497 		 value_16bit );
498 
499 		byte_stream_copy_to_uint64_little_endian(
500 		 ( (fsapfs_file_system_btree_value_inode_t *) data )->unknown4,
501 		 value_64bit );
502 		libcnotify_printf(
503 		 "%s: unknown4\t\t\t\t: 0x%08" PRIx64 "\n",
504 		 function,
505 		 value_64bit );
506 	}
507 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
508 
509 	if( data_size > sizeof( fsapfs_file_system_btree_value_inode_t ) )
510 	{
511 		data_offset = sizeof( fsapfs_file_system_btree_value_inode_t );
512 
513 		if( data_offset > ( data_size - 4 ) )
514 		{
515 			libcerror_error_set(
516 			 error,
517 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
518 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
519 			 "%s: invalid data size value out of bounds.",
520 			 function );
521 
522 			return( -1 );
523 		}
524 		byte_stream_copy_to_uint16_little_endian(
525 		 &( data[ data_offset ] ),
526 		 number_of_extended_fields );
527 
528 #if defined( HAVE_DEBUG_OUTPUT )
529 		if( libcnotify_verbose != 0 )
530 		{
531 			libcnotify_printf(
532 			 "%s: number of extended fields\t\t: %" PRIu16 "\n",
533 			 function,
534 			 number_of_extended_fields );
535 
536 			byte_stream_copy_to_uint16_little_endian(
537 			 &( data[ data_offset + 2 ] ),
538 			 value_16bit );
539 			libcnotify_printf(
540 			 "%s: extended field value data size\t\t: %" PRIu16 "\n",
541 			 function,
542 			 value_16bit );
543 		}
544 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
545 
546 		data_offset      += 4;
547 		value_data_offset = data_offset + ( number_of_extended_fields * 4 );
548 
549 		for( extended_field_index = 0;
550 		     extended_field_index < number_of_extended_fields;
551 		     extended_field_index++ )
552 		{
553 			if( data_offset > ( data_size - 4 ) )
554 			{
555 				libcerror_error_set(
556 				 error,
557 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
558 				 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
559 				 "%s: invalid data size value out of bounds.",
560 				 function );
561 
562 				return( -1 );
563 			}
564 			extended_field_type  = data[ data_offset ];
565 			extended_field_flags = data[ data_offset + 1 ];
566 
567 			byte_stream_copy_to_uint16_little_endian(
568 			 &( data[ data_offset + 2 ] ),
569 			 value_data_size );
570 
571 #if defined( HAVE_DEBUG_OUTPUT )
572 			if( libcnotify_verbose != 0 )
573 			{
574 				libcnotify_printf(
575 				 "%s: extended field: %" PRIu16 " type\t\t\t: %" PRIu8 " %s\n",
576 				 function,
577 				 extended_field_index,
578 				 extended_field_type,
579 				 libfsapfs_debug_print_inode_extended_field_type(
580 				  extended_field_type ) );
581 
582 				libcnotify_printf(
583 				 "%s: extended field: %" PRIu16 " flags\t\t: 0x%02" PRIx8 "\n",
584 				 function,
585 				 extended_field_index,
586 				 extended_field_flags );
587 				libfsapfs_debug_print_extended_field_flags(
588 				 extended_field_flags );
589 				libcnotify_printf(
590 				 "\n" );
591 
592 				libcnotify_printf(
593 				 "%s: extended field: %" PRIu16 " value data size\t: %" PRIu16 "\n",
594 				 function,
595 				 extended_field_index,
596 				 value_data_size );
597 			}
598 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
599 
600 			data_offset += 4;
601 
602 			if( value_data_offset > data_size )
603 			{
604 				libcerror_error_set(
605 				 error,
606 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
607 				 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
608 				 "%s: invalid data size value out of bounds.",
609 				 function );
610 
611 				return( -1 );
612 			}
613 			if( ( value_data_size == 0 )
614 			 || ( (size_t) value_data_size > ( data_size - value_data_offset ) ) )
615 			{
616 				libcerror_error_set(
617 				 error,
618 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
619 				 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
620 				 "%s: invalid value data size value out of bounds.",
621 				 function );
622 
623 				return( -1 );
624 			}
625 			value_data = &( data[ value_data_offset ] );
626 
627 #if defined( HAVE_DEBUG_OUTPUT )
628 			if( libcnotify_verbose != 0 )
629 			{
630 				libcnotify_printf(
631 				 "%s: extended field: %" PRIu16 " value data:\n",
632 				 function,
633 				 extended_field_index );
634 				libcnotify_print_data(
635 				 value_data,
636 				 value_data_size,
637 				 0 );
638 			}
639 #endif
640 			switch( extended_field_type )
641 			{
642 				case 1:
643 				case 2:
644 				case 3:
645 				case 5:
646 				case 7:
647 				case 11:
648 				case 13:
649 				case 14:
650 					break;
651 
652 				case 4:
653 					inode->name = (uint8_t *) memory_allocate(
654 					                           sizeof( uint8_t ) * (size_t) value_data_size );
655 
656 					if( inode->name == NULL )
657 					{
658 						libcerror_error_set(
659 						 error,
660 						 LIBCERROR_ERROR_DOMAIN_MEMORY,
661 						 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
662 						 "%s: unable to create name.",
663 						 function );
664 
665 						goto on_error;
666 					}
667 					inode->name_size = (size_t) value_data_size;
668 
669 					if( memory_copy(
670 					     inode->name,
671 					     value_data,
672 					     (size_t) value_data_size ) == NULL )
673 					{
674 						libcerror_error_set(
675 						 error,
676 						 LIBCERROR_ERROR_DOMAIN_MEMORY,
677 						 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
678 						 "%s: unable to copy name.",
679 						 function );
680 
681 						goto on_error;
682 					}
683 #if defined( HAVE_DEBUG_OUTPUT )
684 					if( libcnotify_verbose != 0 )
685 					{
686 						libcnotify_printf(
687 						 "%s: name\t\t\t\t\t: %s\n",
688 						 function,
689 						 inode->name );
690 					}
691 #endif
692 					break;
693 
694 				case 8:
695 					byte_stream_copy_to_uint64_little_endian(
696 					 ( (fsapfs_file_system_data_stream_attribute_t *) value_data )->used_size,
697 					 inode->data_stream_size );
698 
699 #if defined( HAVE_DEBUG_OUTPUT )
700 					if( libcnotify_verbose != 0 )
701 					{
702 						libcnotify_printf(
703 						 "%s: used size\t\t\t\t: %" PRIu64 "\n",
704 						 function,
705 						 inode->data_stream_size );
706 
707 						byte_stream_copy_to_uint64_little_endian(
708 						 ( (fsapfs_file_system_data_stream_attribute_t *) value_data )->allocated_size,
709 						 value_64bit );
710 						libcnotify_printf(
711 						 "%s: allocated size\t\t\t\t: %" PRIu64 "\n",
712 						 function,
713 						 value_64bit );
714 
715 						byte_stream_copy_to_uint64_little_endian(
716 						 ( (fsapfs_file_system_data_stream_attribute_t *) value_data )->encryption_identifier,
717 						 value_64bit );
718 						libcnotify_printf(
719 						 "%s: encryption identifier\t\t\t: %" PRIu64 "\n",
720 						 function,
721 						 value_64bit );
722 
723 						byte_stream_copy_to_uint64_little_endian(
724 						 ( (fsapfs_file_system_data_stream_attribute_t *) value_data )->number_of_bytes_written,
725 						 value_64bit );
726 						libcnotify_printf(
727 						 "%s: number of bytes written\t\t: %" PRIu64 "\n",
728 						 function,
729 						 value_64bit );
730 
731 						byte_stream_copy_to_uint64_little_endian(
732 						 ( (fsapfs_file_system_data_stream_attribute_t *) value_data )->number_of_bytes_read,
733 						 value_64bit );
734 						libcnotify_printf(
735 						 "%s: number of bytes read\t\t\t: %" PRIu64 "\n",
736 						 function,
737 						 value_64bit );
738 
739 						libcnotify_printf(
740 						 "\n" );
741 					}
742 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
743 					break;
744 
745 				default:
746 					libcerror_error_set(
747 					 error,
748 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
749 					 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
750 					 "%s: unsupported extended field type: %" PRIu8 ".",
751 					 function,
752 					 extended_field_type );
753 
754 					return( -1 );
755 			}
756 			value_data_offset += value_data_size;
757 
758 			trailing_data_size = value_data_size % 8;
759 
760 			if( trailing_data_size > 0 )
761 			{
762 				trailing_data_size = 8 - trailing_data_size;
763 
764 				if( value_data_offset > ( data_size - trailing_data_size ) )
765 				{
766 					trailing_data_size = data_size - value_data_offset;
767 				}
768 #if defined( HAVE_DEBUG_OUTPUT )
769 				if( libcnotify_verbose != 0 )
770 				{
771 					libcnotify_printf(
772 					 "%s: extended field: %" PRIu16 " trailing data:\n",
773 					 function,
774 					 extended_field_index );
775 					libcnotify_print_data(
776 					 &( data[ value_data_offset ] ),
777 					 trailing_data_size,
778 					 0 );
779 				}
780 #endif
781 				value_data_offset += trailing_data_size;
782 			}
783 		}
784 	}
785 #if defined( HAVE_DEBUG_OUTPUT )
786 	else if( libcnotify_verbose != 0 )
787 	{
788 		libcnotify_printf(
789 		 "\n" );
790 	}
791 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
792 
793 	return( 1 );
794 
795 on_error:
796 	if( inode->name != NULL )
797 	{
798 		memory_free(
799 		 inode->name );
800 
801 		inode->name = NULL;
802 	}
803 	inode->name_size = 0;
804 
805 	return( -1 );
806 }
807 
808 /* Retrieves the identifier
809  * Returns 1 if successful or -1 on error
810  */
libfsapfs_inode_get_identifier(libfsapfs_inode_t * inode,uint64_t * identifier,libcerror_error_t ** error)811 int libfsapfs_inode_get_identifier(
812      libfsapfs_inode_t *inode,
813      uint64_t *identifier,
814      libcerror_error_t **error )
815 {
816 	static char *function = "libfsapfs_inode_get_identifier";
817 
818 	if( inode == NULL )
819 	{
820 		libcerror_error_set(
821 		 error,
822 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
823 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
824 		 "%s: invalid inode.",
825 		 function );
826 
827 		return( -1 );
828 	}
829 	if( identifier == NULL )
830 	{
831 		libcerror_error_set(
832 		 error,
833 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
834 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
835 		 "%s: invalid identifier.",
836 		 function );
837 
838 		return( -1 );
839 	}
840 	*identifier = inode->identifier;
841 
842 	return( 1 );
843 }
844 
845 /* Retrieves the parent identifier
846  * Returns 1 if successful or -1 on error
847  */
libfsapfs_inode_get_parent_identifier(libfsapfs_inode_t * inode,uint64_t * parent_identifier,libcerror_error_t ** error)848 int libfsapfs_inode_get_parent_identifier(
849      libfsapfs_inode_t *inode,
850      uint64_t *parent_identifier,
851      libcerror_error_t **error )
852 {
853 	static char *function = "libfsapfs_inode_get_parent_identifier";
854 
855 	if( inode == NULL )
856 	{
857 		libcerror_error_set(
858 		 error,
859 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
860 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
861 		 "%s: invalid inode.",
862 		 function );
863 
864 		return( -1 );
865 	}
866 	if( parent_identifier == NULL )
867 	{
868 		libcerror_error_set(
869 		 error,
870 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
871 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
872 		 "%s: invalid parent identifier.",
873 		 function );
874 
875 		return( -1 );
876 	}
877 	*parent_identifier = inode->parent_identifier;
878 
879 	return( 1 );
880 }
881 
882 /* Retrieves the creation time
883  * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
884  * Returns 1 if successful or -1 on error
885  */
libfsapfs_inode_get_creation_time(libfsapfs_inode_t * inode,int64_t * posix_time,libcerror_error_t ** error)886 int libfsapfs_inode_get_creation_time(
887      libfsapfs_inode_t *inode,
888      int64_t *posix_time,
889      libcerror_error_t **error )
890 {
891 	static char *function = "libfsapfs_inode_get_creation_time";
892 
893 	if( inode == NULL )
894 	{
895 		libcerror_error_set(
896 		 error,
897 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
898 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
899 		 "%s: invalid inode.",
900 		 function );
901 
902 		return( -1 );
903 	}
904 	if( posix_time == NULL )
905 	{
906 		libcerror_error_set(
907 		 error,
908 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
909 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
910 		 "%s: invalid POSIX time.",
911 		 function );
912 
913 		return( -1 );
914 	}
915 	*posix_time = (int64_t) inode->creation_time;
916 
917 	return( 1 );
918 }
919 
920 /* Retrieves the modification time
921  * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
922  * Returns 1 if successful or -1 on error
923  */
libfsapfs_inode_get_modification_time(libfsapfs_inode_t * inode,int64_t * posix_time,libcerror_error_t ** error)924 int libfsapfs_inode_get_modification_time(
925      libfsapfs_inode_t *inode,
926      int64_t *posix_time,
927      libcerror_error_t **error )
928 {
929 	static char *function = "libfsapfs_inode_get_modification_time";
930 
931 	if( inode == NULL )
932 	{
933 		libcerror_error_set(
934 		 error,
935 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
936 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
937 		 "%s: invalid inode.",
938 		 function );
939 
940 		return( -1 );
941 	}
942 	if( posix_time == NULL )
943 	{
944 		libcerror_error_set(
945 		 error,
946 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
947 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
948 		 "%s: invalid POSIX time.",
949 		 function );
950 
951 		return( -1 );
952 	}
953 	*posix_time = (int64_t) inode->modification_time;
954 
955 	return( 1 );
956 }
957 
958 /* Retrieves the inode change time
959  * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
960  * Returns 1 if successful or -1 on error
961  */
libfsapfs_inode_get_inode_change_time(libfsapfs_inode_t * inode,int64_t * posix_time,libcerror_error_t ** error)962 int libfsapfs_inode_get_inode_change_time(
963      libfsapfs_inode_t *inode,
964      int64_t *posix_time,
965      libcerror_error_t **error )
966 {
967 	static char *function = "libfsapfs_inode_get_inode_change_time";
968 
969 	if( inode == NULL )
970 	{
971 		libcerror_error_set(
972 		 error,
973 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
974 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
975 		 "%s: invalid inode.",
976 		 function );
977 
978 		return( -1 );
979 	}
980 	if( posix_time == NULL )
981 	{
982 		libcerror_error_set(
983 		 error,
984 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
985 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
986 		 "%s: invalid POSIX time.",
987 		 function );
988 
989 		return( -1 );
990 	}
991 	*posix_time = (int64_t) inode->inode_change_time;
992 
993 	return( 1 );
994 }
995 
996 /* Retrieves the access time
997  * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
998  * Returns 1 if successful or -1 on error
999  */
libfsapfs_inode_get_access_time(libfsapfs_inode_t * inode,int64_t * posix_time,libcerror_error_t ** error)1000 int libfsapfs_inode_get_access_time(
1001      libfsapfs_inode_t *inode,
1002      int64_t *posix_time,
1003      libcerror_error_t **error )
1004 {
1005 	static char *function = "libfsapfs_inode_get_access_time";
1006 
1007 	if( inode == NULL )
1008 	{
1009 		libcerror_error_set(
1010 		 error,
1011 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1012 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1013 		 "%s: invalid inode.",
1014 		 function );
1015 
1016 		return( -1 );
1017 	}
1018 	if( posix_time == NULL )
1019 	{
1020 		libcerror_error_set(
1021 		 error,
1022 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1023 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1024 		 "%s: invalid POSIX time.",
1025 		 function );
1026 
1027 		return( -1 );
1028 	}
1029 	*posix_time = (int64_t) inode->access_time;
1030 
1031 	return( 1 );
1032 }
1033 
1034 /* Retrieves the owner identifier
1035  * Returns 1 if successful or -1 on error
1036  */
libfsapfs_inode_get_owner_identifier(libfsapfs_inode_t * inode,uint32_t * owner_identifier,libcerror_error_t ** error)1037 int libfsapfs_inode_get_owner_identifier(
1038      libfsapfs_inode_t *inode,
1039      uint32_t *owner_identifier,
1040      libcerror_error_t **error )
1041 {
1042 	static char *function = "libfsapfs_inode_get_owner_identifier";
1043 
1044 	if( inode == NULL )
1045 	{
1046 		libcerror_error_set(
1047 		 error,
1048 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1049 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1050 		 "%s: invalid inode.",
1051 		 function );
1052 
1053 		return( -1 );
1054 	}
1055 	if( owner_identifier == NULL )
1056 	{
1057 		libcerror_error_set(
1058 		 error,
1059 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1060 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1061 		 "%s: invalid owner identifier.",
1062 		 function );
1063 
1064 		return( -1 );
1065 	}
1066 	*owner_identifier = inode->owner_identifier;
1067 
1068 	return( 1 );
1069 }
1070 
1071 /* Retrieves the group identifier
1072  * Returns 1 if successful or -1 on error
1073  */
libfsapfs_inode_get_group_identifier(libfsapfs_inode_t * inode,uint32_t * group_identifier,libcerror_error_t ** error)1074 int libfsapfs_inode_get_group_identifier(
1075      libfsapfs_inode_t *inode,
1076      uint32_t *group_identifier,
1077      libcerror_error_t **error )
1078 {
1079 	static char *function = "libfsapfs_inode_get_group_identifier";
1080 
1081 	if( inode == NULL )
1082 	{
1083 		libcerror_error_set(
1084 		 error,
1085 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1086 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1087 		 "%s: invalid inode.",
1088 		 function );
1089 
1090 		return( -1 );
1091 	}
1092 	if( group_identifier == NULL )
1093 	{
1094 		libcerror_error_set(
1095 		 error,
1096 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1097 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1098 		 "%s: invalid group identifier.",
1099 		 function );
1100 
1101 		return( -1 );
1102 	}
1103 	*group_identifier = inode->group_identifier;
1104 
1105 	return( 1 );
1106 }
1107 
1108 /* Retrieves the file mode
1109  * Returns 1 if successful or -1 on error
1110  */
libfsapfs_inode_get_file_mode(libfsapfs_inode_t * inode,uint16_t * file_mode,libcerror_error_t ** error)1111 int libfsapfs_inode_get_file_mode(
1112      libfsapfs_inode_t *inode,
1113      uint16_t *file_mode,
1114      libcerror_error_t **error )
1115 {
1116 	static char *function = "libfsapfs_inode_get_file_mode";
1117 
1118 	if( inode == NULL )
1119 	{
1120 		libcerror_error_set(
1121 		 error,
1122 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1123 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1124 		 "%s: invalid inode.",
1125 		 function );
1126 
1127 		return( -1 );
1128 	}
1129 	if( file_mode == NULL )
1130 	{
1131 		libcerror_error_set(
1132 		 error,
1133 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1134 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1135 		 "%s: invalid file mode.",
1136 		 function );
1137 
1138 		return( -1 );
1139 	}
1140 	*file_mode = inode->file_mode;
1141 
1142 	return( 1 );
1143 }
1144 
1145 /* Retrieves the size of the UTF-8 encoded name
1146  * The returned size includes the end of string character
1147  * Returns 1 if successful or -1 on error
1148  */
libfsapfs_inode_get_utf8_name_size(libfsapfs_inode_t * inode,size_t * utf8_string_size,libcerror_error_t ** error)1149 int libfsapfs_inode_get_utf8_name_size(
1150      libfsapfs_inode_t *inode,
1151      size_t *utf8_string_size,
1152      libcerror_error_t **error )
1153 {
1154 	static char *function = "libfsapfs_inode_get_utf8_name_size";
1155 
1156 	if( inode == NULL )
1157 	{
1158 		libcerror_error_set(
1159 		 error,
1160 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1161 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1162 		 "%s: invalid inode.",
1163 		 function );
1164 
1165 		return( -1 );
1166 	}
1167 	if( libuna_utf8_string_size_from_utf8_stream(
1168 	     inode->name,
1169 	     (size_t) inode->name_size,
1170 	     utf8_string_size,
1171 	     error ) != 1 )
1172 	{
1173 		libcerror_error_set(
1174 		 error,
1175 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1176 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1177 		 "%s: unable to retrieve UTF-8 string size.",
1178 		 function );
1179 
1180 		return( -1 );
1181 	}
1182 	return( 1 );
1183 }
1184 
1185 /* Retrieves the UTF-8 encoded name
1186  * The size should include the end of string character
1187  * Returns 1 if successful or -1 on error
1188  */
libfsapfs_inode_get_utf8_name(libfsapfs_inode_t * inode,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)1189 int libfsapfs_inode_get_utf8_name(
1190      libfsapfs_inode_t *inode,
1191      uint8_t *utf8_string,
1192      size_t utf8_string_size,
1193      libcerror_error_t **error )
1194 {
1195 	static char *function = "libfsapfs_inode_get_utf8_name";
1196 
1197 	if( inode == NULL )
1198 	{
1199 		libcerror_error_set(
1200 		 error,
1201 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1202 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1203 		 "%s: invalid inode.",
1204 		 function );
1205 
1206 		return( -1 );
1207 	}
1208 	if( libuna_utf8_string_copy_from_utf8_stream(
1209 	     utf8_string,
1210 	     utf8_string_size,
1211 	     inode->name,
1212 	     (size_t) inode->name_size,
1213 	     error ) != 1 )
1214 	{
1215 		libcerror_error_set(
1216 		 error,
1217 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1218 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1219 		 "%s: unable to retrieve UTF-8 string.",
1220 		 function );
1221 
1222 		return( -1 );
1223 	}
1224 	return( 1 );
1225 }
1226 
1227 /* Retrieves the size of the UTF-16 encoded name
1228  * The returned size includes the end of string character
1229  * Returns 1 if successful or -1 on error
1230  */
libfsapfs_inode_get_utf16_name_size(libfsapfs_inode_t * inode,size_t * utf16_string_size,libcerror_error_t ** error)1231 int libfsapfs_inode_get_utf16_name_size(
1232      libfsapfs_inode_t *inode,
1233      size_t *utf16_string_size,
1234      libcerror_error_t **error )
1235 {
1236 	static char *function = "libfsapfs_inode_get_utf16_name_size";
1237 
1238 	if( inode == NULL )
1239 	{
1240 		libcerror_error_set(
1241 		 error,
1242 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1243 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1244 		 "%s: invalid inode.",
1245 		 function );
1246 
1247 		return( -1 );
1248 	}
1249 	if( libuna_utf16_string_size_from_utf8_stream(
1250 	     inode->name,
1251 	     (size_t) inode->name_size,
1252 	     utf16_string_size,
1253 	     error ) != 1 )
1254 	{
1255 		libcerror_error_set(
1256 		 error,
1257 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1258 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1259 		 "%s: unable to retrieve UTF-16 string size.",
1260 		 function );
1261 
1262 		return( -1 );
1263 	}
1264 	return( 1 );
1265 }
1266 
1267 /* Retrieves the UTF-16 encoded name
1268  * The size should include the end of string character
1269  * Returns 1 if successful or -1 on error
1270  */
libfsapfs_inode_get_utf16_name(libfsapfs_inode_t * inode,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)1271 int libfsapfs_inode_get_utf16_name(
1272      libfsapfs_inode_t *inode,
1273      uint16_t *utf16_string,
1274      size_t utf16_string_size,
1275      libcerror_error_t **error )
1276 {
1277 	static char *function = "libfsapfs_inode_get_utf16_name";
1278 
1279 	if( inode == NULL )
1280 	{
1281 		libcerror_error_set(
1282 		 error,
1283 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1284 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1285 		 "%s: invalid inode.",
1286 		 function );
1287 
1288 		return( -1 );
1289 	}
1290 	if( libuna_utf16_string_copy_from_utf8_stream(
1291 	     utf16_string,
1292 	     utf16_string_size,
1293 	     inode->name,
1294 	     (size_t) inode->name_size,
1295 	     error ) != 1 )
1296 	{
1297 		libcerror_error_set(
1298 		 error,
1299 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1300 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1301 		 "%s: unable to retrieve UTF-16 string.",
1302 		 function );
1303 
1304 		return( -1 );
1305 	}
1306 	return( 1 );
1307 }
1308 
1309 /* Retrieves the flags
1310  * Returns 1 if successful or -1 on error
1311  */
libfsapfs_inode_get_flags(libfsapfs_inode_t * inode,uint64_t * flags,libcerror_error_t ** error)1312 int libfsapfs_inode_get_flags(
1313      libfsapfs_inode_t *inode,
1314      uint64_t *flags,
1315      libcerror_error_t **error )
1316 {
1317 	static char *function = "libfsapfs_inode_get_flags";
1318 
1319 	if( inode == NULL )
1320 	{
1321 		libcerror_error_set(
1322 		 error,
1323 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1324 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1325 		 "%s: invalid inode.",
1326 		 function );
1327 
1328 		return( -1 );
1329 	}
1330 	if( flags == NULL )
1331 	{
1332 		libcerror_error_set(
1333 		 error,
1334 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1335 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1336 		 "%s: invalid flags.",
1337 		 function );
1338 
1339 		return( -1 );
1340 	}
1341 	*flags = inode->flags;
1342 
1343 	return( 1 );
1344 }
1345 
1346 /* Retrieves the data stream identifier
1347  * Returns 1 if successful or -1 on error
1348  */
libfsapfs_inode_get_data_stream_identifier(libfsapfs_inode_t * inode,uint64_t * data_stream_identifier,libcerror_error_t ** error)1349 int libfsapfs_inode_get_data_stream_identifier(
1350      libfsapfs_inode_t *inode,
1351      uint64_t *data_stream_identifier,
1352      libcerror_error_t **error )
1353 {
1354 	static char *function = "libfsapfs_inode_get_data_stream_identifier";
1355 
1356 	if( inode == NULL )
1357 	{
1358 		libcerror_error_set(
1359 		 error,
1360 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1361 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1362 		 "%s: invalid inode.",
1363 		 function );
1364 
1365 		return( -1 );
1366 	}
1367 	if( data_stream_identifier == NULL )
1368 	{
1369 		libcerror_error_set(
1370 		 error,
1371 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1372 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1373 		 "%s: invalid data stream identifier.",
1374 		 function );
1375 
1376 		return( -1 );
1377 	}
1378 	*data_stream_identifier = inode->data_stream_identifier;
1379 
1380 	return( 1 );
1381 }
1382 
1383 /* Retrieves the data stream size
1384  * Returns 1 if successful or -1 on error
1385  */
libfsapfs_inode_get_data_stream_size(libfsapfs_inode_t * inode,uint64_t * data_stream_size,libcerror_error_t ** error)1386 int libfsapfs_inode_get_data_stream_size(
1387      libfsapfs_inode_t *inode,
1388      uint64_t *data_stream_size,
1389      libcerror_error_t **error )
1390 {
1391 	static char *function = "libfsapfs_inode_get_data_stream_size";
1392 
1393 	if( inode == NULL )
1394 	{
1395 		libcerror_error_set(
1396 		 error,
1397 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1398 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1399 		 "%s: invalid inode.",
1400 		 function );
1401 
1402 		return( -1 );
1403 	}
1404 	if( data_stream_size == NULL )
1405 	{
1406 		libcerror_error_set(
1407 		 error,
1408 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1409 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1410 		 "%s: invalid data stream size.",
1411 		 function );
1412 
1413 		return( -1 );
1414 	}
1415 	*data_stream_size = inode->data_stream_size;
1416 
1417 	return( 1 );
1418 }
1419 
1420