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