Coverage Report

Created: 2026-07-25 07:30

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