Coverage Report

Created: 2026-03-05 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsapfs/libfsapfs/libfsapfs_file_entry.c
Line
Count
Source
1
/*
2
 * File entry functions
3
 *
4
 * Copyright (C) 2018-2025, 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 <memory.h>
24
#include <types.h>
25
26
#include "libfsapfs_attribute_values.h"
27
#include "libfsapfs_attributes.h"
28
#include "libfsapfs_compressed_data_header.h"
29
#include "libfsapfs_data_stream.h"
30
#include "libfsapfs_definitions.h"
31
#include "libfsapfs_directory_record.h"
32
#include "libfsapfs_encryption_context.h"
33
#include "libfsapfs_extended_attribute.h"
34
#include "libfsapfs_file_entry.h"
35
#include "libfsapfs_file_extent.h"
36
#include "libfsapfs_file_system_btree.h"
37
#include "libfsapfs_inode.h"
38
#include "libfsapfs_io_handle.h"
39
#include "libfsapfs_libbfio.h"
40
#include "libfsapfs_libcdata.h"
41
#include "libfsapfs_libcerror.h"
42
#include "libfsapfs_libcnotify.h"
43
#include "libfsapfs_libcthreads.h"
44
#include "libfsapfs_libfdata.h"
45
#include "libfsapfs_libuna.h"
46
#include "libfsapfs_types.h"
47
48
#include "fsapfs_file_system.h"
49
50
/* Creates a file entry
51
 * Make sure the value file_entry is referencing, is set to NULL
52
 * Returns 1 if successful or -1 on error
53
 */
54
int libfsapfs_file_entry_initialize(
55
     libfsapfs_file_entry_t **file_entry,
56
     libfsapfs_io_handle_t *io_handle,
57
     libbfio_handle_t *file_io_handle,
58
     libfsapfs_encryption_context_t *encryption_context,
59
     libfsapfs_file_system_btree_t *file_system_btree,
60
     libfsapfs_inode_t *inode,
61
     libfsapfs_directory_record_t *directory_record,
62
     uint64_t transaction_identifier,
63
     libcerror_error_t **error )
64
1.68k
{
65
1.68k
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
66
1.68k
  static char *function                                = "libfsapfs_file_entry_initialize";
67
68
1.68k
  if( file_entry == NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
74
0
     "%s: invalid file entry.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
1.68k
  if( *file_entry != NULL )
80
0
  {
81
0
    libcerror_error_set(
82
0
     error,
83
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
84
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
85
0
     "%s: invalid file entry value already set.",
86
0
     function );
87
88
0
    return( -1 );
89
0
  }
90
1.68k
  internal_file_entry = memory_allocate_structure(
91
1.68k
                         libfsapfs_internal_file_entry_t );
92
93
1.68k
  if( internal_file_entry == NULL )
94
0
  {
95
0
    libcerror_error_set(
96
0
     error,
97
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
98
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
99
0
     "%s: unable to create file entry.",
100
0
     function );
101
102
0
    goto on_error;
103
0
  }
104
1.68k
  if( memory_set(
105
1.68k
       internal_file_entry,
106
1.68k
       0,
107
1.68k
       sizeof( libfsapfs_internal_file_entry_t ) ) == NULL )
108
0
  {
109
0
    libcerror_error_set(
110
0
     error,
111
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
112
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
113
0
     "%s: unable to clear file entry.",
114
0
     function );
115
116
0
    memory_free(
117
0
     internal_file_entry );
118
119
0
    return( -1 );
120
0
  }
121
1.68k
  internal_file_entry->io_handle              = io_handle;
122
1.68k
  internal_file_entry->file_io_handle         = file_io_handle;
123
1.68k
  internal_file_entry->encryption_context     = encryption_context;
124
1.68k
  internal_file_entry->file_system_btree      = file_system_btree;
125
1.68k
  internal_file_entry->inode                  = inode;
126
1.68k
  internal_file_entry->directory_record       = directory_record;
127
1.68k
  internal_file_entry->transaction_identifier = transaction_identifier;
128
1.68k
  internal_file_entry->data_size              = (size64_t) -1;
129
130
1.68k
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSAPFS )
131
1.68k
  if( libcthreads_read_write_lock_initialize(
132
1.68k
       &( internal_file_entry->read_write_lock ),
133
1.68k
       error ) != 1 )
134
0
  {
135
0
    libcerror_error_set(
136
0
     error,
137
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
138
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
139
0
     "%s: unable to initialize read/write lock.",
140
0
     function );
141
142
0
    goto on_error;
143
0
  }
144
1.68k
#endif
145
1.68k
  *file_entry = (libfsapfs_file_entry_t *) internal_file_entry;
146
147
1.68k
  return( 1 );
148
149
0
on_error:
150
0
  if( internal_file_entry != NULL )
151
0
  {
152
0
    memory_free(
153
0
     internal_file_entry );
154
0
  }
155
0
  return( -1 );
156
1.68k
}
157
158
/* Frees a file entry
159
 * Returns 1 if successful or -1 on error
160
 */
161
int libfsapfs_file_entry_free(
162
     libfsapfs_file_entry_t **file_entry,
163
     libcerror_error_t **error )
164
1.73k
{
165
1.73k
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
166
1.73k
  static char *function                                = "libfsapfs_file_entry_free";
167
1.73k
  int result                                           = 1;
168
169
1.73k
  if( file_entry == NULL )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
174
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
175
0
     "%s: invalid file entry.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
1.73k
  if( *file_entry != NULL )
181
1.68k
  {
182
1.68k
    internal_file_entry = (libfsapfs_internal_file_entry_t *) *file_entry;
183
1.68k
    *file_entry         = NULL;
184
185
1.68k
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSAPFS )
186
1.68k
    if( libcthreads_read_write_lock_free(
187
1.68k
         &( internal_file_entry->read_write_lock ),
188
1.68k
         error ) != 1 )
189
0
    {
190
0
      libcerror_error_set(
191
0
       error,
192
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
193
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
194
0
       "%s: unable to free read/write lock.",
195
0
       function );
196
197
0
      result = -1;
198
0
    }
199
1.68k
#endif
200
    /* The file_io_handle and file_system_btree references are freed elsewhere
201
     */
202
1.68k
    if( internal_file_entry->inode != NULL )
203
1.68k
    {
204
1.68k
      if( libfsapfs_inode_free(
205
1.68k
           &( internal_file_entry->inode ),
206
1.68k
           error ) != 1 )
207
0
      {
208
0
        libcerror_error_set(
209
0
         error,
210
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
211
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
212
0
         "%s: unable to free inode.",
213
0
         function );
214
215
0
        result = -1;
216
0
      }
217
1.68k
    }
218
1.68k
    if( internal_file_entry->directory_record != NULL )
219
859
    {
220
859
      if( libfsapfs_directory_record_free(
221
859
           &( internal_file_entry->directory_record ),
222
859
           error ) != 1 )
223
0
      {
224
0
        libcerror_error_set(
225
0
         error,
226
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
227
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
228
0
         "%s: unable to free directory record.",
229
0
         function );
230
231
0
        result = -1;
232
0
      }
233
859
    }
234
1.68k
    if( internal_file_entry->extended_attributes_array != NULL )
235
637
    {
236
637
      if( libcdata_array_free(
237
637
           &( internal_file_entry->extended_attributes_array ),
238
637
           (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_attribute_values_free,
239
637
           error ) != 1 )
240
0
      {
241
0
        libcerror_error_set(
242
0
         error,
243
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
244
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
245
0
         "%s: unable to free extended attributes array.",
246
0
         function );
247
248
0
        result = -1;
249
0
      }
250
637
    }
251
1.68k
    if( internal_file_entry->compressed_data_header != NULL )
252
0
    {
253
0
      if( libfsapfs_compressed_data_header_free(
254
0
           &( internal_file_entry->compressed_data_header ),
255
0
           error ) != 1 )
256
0
      {
257
0
        libcerror_error_set(
258
0
         error,
259
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
260
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
261
0
         "%s: unable to free compressed data header.",
262
0
         function );
263
264
0
        result = -1;
265
0
      }
266
0
    }
267
1.68k
    if( internal_file_entry->symbolic_link_data != NULL )
268
5
    {
269
5
      memory_free(
270
5
       internal_file_entry->symbolic_link_data );
271
5
    }
272
1.68k
    if( internal_file_entry->directory_entries != NULL )
273
742
    {
274
742
      if( libcdata_array_free(
275
742
           &( internal_file_entry->directory_entries ),
276
742
           (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_directory_record_free,
277
742
           error ) != 1 )
278
0
      {
279
0
        libcerror_error_set(
280
0
         error,
281
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
282
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
283
0
         "%s: unable to free directory entries array.",
284
0
         function );
285
286
0
        result = -1;
287
0
      }
288
742
    }
289
1.68k
    if( internal_file_entry->file_extents != NULL )
290
520
    {
291
520
      if( libcdata_array_free(
292
520
           &( internal_file_entry->file_extents ),
293
520
           (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
294
520
           error ) != 1 )
295
0
      {
296
0
        libcerror_error_set(
297
0
         error,
298
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
299
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
300
0
         "%s: unable to free file extents array.",
301
0
         function );
302
303
0
        result = -1;
304
0
      }
305
520
    }
306
1.68k
    if( internal_file_entry->data_stream != NULL )
307
205
    {
308
205
      if( libfdata_stream_free(
309
205
           &( internal_file_entry->data_stream ),
310
205
           error ) != 1 )
311
0
      {
312
0
        libcerror_error_set(
313
0
         error,
314
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
315
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
316
0
         "%s: unable to free data stream.",
317
0
         function );
318
319
0
        result = -1;
320
0
      }
321
205
    }
322
1.68k
    memory_free(
323
1.68k
     internal_file_entry );
324
1.68k
  }
325
1.73k
  return( result );
326
1.73k
}
327
328
/* Retrieves the identifier
329
 * This value is retrieved from the inode
330
 * Returns 1 if successful or -1 on error
331
 */
332
int libfsapfs_file_entry_get_identifier(
333
     libfsapfs_file_entry_t *file_entry,
334
     uint64_t *identifier,
335
     libcerror_error_t **error )
336
616
{
337
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
338
616
  static char *function                                = "libfsapfs_file_entry_get_identifier";
339
616
  int result                                           = 1;
340
341
616
  if( file_entry == NULL )
342
0
  {
343
0
    libcerror_error_set(
344
0
     error,
345
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
346
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
347
0
     "%s: invalid file entry.",
348
0
     function );
349
350
0
    return( -1 );
351
0
  }
352
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
353
354
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
355
616
  if( libcthreads_read_write_lock_grab_for_read(
356
616
       internal_file_entry->read_write_lock,
357
616
       error ) != 1 )
358
0
  {
359
0
    libcerror_error_set(
360
0
     error,
361
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
362
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
363
0
     "%s: unable to grab read/write lock for reading.",
364
0
     function );
365
366
0
    return( -1 );
367
0
  }
368
616
#endif
369
616
  if( libfsapfs_inode_get_identifier(
370
616
       internal_file_entry->inode,
371
616
       identifier,
372
616
       error ) != 1 )
373
0
  {
374
0
    libcerror_error_set(
375
0
     error,
376
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
377
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
378
0
     "%s: unable to retrieve identifier.",
379
0
     function );
380
381
0
    result = -1;
382
0
  }
383
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
384
616
  if( libcthreads_read_write_lock_release_for_read(
385
616
       internal_file_entry->read_write_lock,
386
616
       error ) != 1 )
387
0
  {
388
0
    libcerror_error_set(
389
0
     error,
390
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
391
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
392
0
     "%s: unable to release read/write lock for reading.",
393
0
     function );
394
395
0
    return( -1 );
396
0
  }
397
616
#endif
398
616
  return( result );
399
616
}
400
401
/* Retrieves the parent identifier
402
 * This value is retrieved from the inode
403
 * Returns 1 if successful or -1 on error
404
 */
405
int libfsapfs_file_entry_get_parent_identifier(
406
     libfsapfs_file_entry_t *file_entry,
407
     uint64_t *parent_identifier,
408
     libcerror_error_t **error )
409
616
{
410
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
411
616
  static char *function                                = "libfsapfs_file_entry_get_parent_identifier";
412
616
  int result                                           = 1;
413
414
616
  if( file_entry == NULL )
415
0
  {
416
0
    libcerror_error_set(
417
0
     error,
418
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
419
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
420
0
     "%s: invalid file entry.",
421
0
     function );
422
423
0
    return( -1 );
424
0
  }
425
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
426
427
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
428
616
  if( libcthreads_read_write_lock_grab_for_read(
429
616
       internal_file_entry->read_write_lock,
430
616
       error ) != 1 )
431
0
  {
432
0
    libcerror_error_set(
433
0
     error,
434
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
435
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
436
0
     "%s: unable to grab read/write lock for reading.",
437
0
     function );
438
439
0
    return( -1 );
440
0
  }
441
616
#endif
442
616
  if( libfsapfs_inode_get_parent_identifier(
443
616
       internal_file_entry->inode,
444
616
       parent_identifier,
445
616
       error ) != 1 )
446
0
  {
447
0
    libcerror_error_set(
448
0
     error,
449
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
450
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
451
0
     "%s: unable to retrieve parent identifier.",
452
0
     function );
453
454
0
    result = -1;
455
0
  }
456
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
457
616
  if( libcthreads_read_write_lock_release_for_read(
458
616
       internal_file_entry->read_write_lock,
459
616
       error ) != 1 )
460
0
  {
461
0
    libcerror_error_set(
462
0
     error,
463
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
464
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
465
0
     "%s: unable to release read/write lock for reading.",
466
0
     function );
467
468
0
    return( -1 );
469
0
  }
470
616
#endif
471
616
  return( result );
472
616
}
473
474
/* Retrieves the parent file entry
475
 * Returns 1 if successful, 0 if no such file entry or -1 on error
476
 */
477
int libfsapfs_file_entry_get_parent_file_entry(
478
     libfsapfs_file_entry_t *file_entry,
479
     libfsapfs_file_entry_t **parent_file_entry,
480
     libcerror_error_t **error )
481
0
{
482
0
  libfsapfs_inode_t *inode                             = NULL;
483
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
484
0
  static char *function                                = "libfsapfs_file_entry_get_parent_file_entry";
485
0
  int result                                           = 0;
486
0
  uint64_t file_system_identifier                      = 0;
487
488
0
  if( file_entry == NULL )
489
0
  {
490
0
    libcerror_error_set(
491
0
     error,
492
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
493
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
494
0
     "%s: invalid file entry.",
495
0
     function );
496
497
0
    return( -1 );
498
0
  }
499
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
500
501
0
  if( parent_file_entry == NULL )
502
0
  {
503
0
    libcerror_error_set(
504
0
     error,
505
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
506
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
507
0
     "%s: invalid parent file entry.",
508
0
     function );
509
510
0
    return( -1 );
511
0
  }
512
0
  if( *parent_file_entry != NULL )
513
0
  {
514
0
    libcerror_error_set(
515
0
     error,
516
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
517
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
518
0
     "%s: invalid parent file entry value already set.",
519
0
     function );
520
521
0
    return( -1 );
522
0
  }
523
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
524
0
  if( libcthreads_read_write_lock_grab_for_write(
525
0
       internal_file_entry->read_write_lock,
526
0
       error ) != 1 )
527
0
  {
528
0
    libcerror_error_set(
529
0
     error,
530
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
531
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
532
0
     "%s: unable to grab read/write lock for writing.",
533
0
     function );
534
535
0
    return( -1 );
536
0
  }
537
0
#endif
538
0
  if( libfsapfs_inode_get_identifier(
539
0
       internal_file_entry->inode,
540
0
       &file_system_identifier,
541
0
       error ) != 1 )
542
0
  {
543
0
    libcerror_error_set(
544
0
     error,
545
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
546
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
547
0
     "%s: unable to retrieve identifier.",
548
0
     function );
549
550
0
    goto on_error;
551
0
  }
552
0
  if( file_system_identifier > 2 )
553
0
  {
554
0
    if( libfsapfs_inode_get_parent_identifier(
555
0
         internal_file_entry->inode,
556
0
         &file_system_identifier,
557
0
         error ) != 1 )
558
0
    {
559
0
      libcerror_error_set(
560
0
       error,
561
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
562
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
563
0
       "%s: unable to retrieve parent identifier.",
564
0
       function );
565
566
0
      goto on_error;
567
0
    }
568
0
    if( libfsapfs_file_system_btree_get_inode_by_identifier(
569
0
         internal_file_entry->file_system_btree,
570
0
         internal_file_entry->file_io_handle,
571
0
         file_system_identifier,
572
0
         internal_file_entry->transaction_identifier,
573
0
         &inode,
574
0
         error ) != 1 )
575
0
    {
576
0
      libcerror_error_set(
577
0
       error,
578
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
579
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
580
0
       "%s: unable to retrieve parent inode: %" PRIu64 " from file system B-tree.",
581
0
       function,
582
0
       file_system_identifier );
583
584
0
       goto on_error;
585
0
    }
586
0
    if( libfsapfs_file_entry_initialize(
587
0
         parent_file_entry,
588
0
         internal_file_entry->io_handle,
589
0
         internal_file_entry->file_io_handle,
590
0
         internal_file_entry->encryption_context,
591
0
         internal_file_entry->file_system_btree,
592
0
         inode,
593
0
         NULL,
594
0
         internal_file_entry->transaction_identifier,
595
0
         error ) != 1 )
596
0
    {
597
0
      libcerror_error_set(
598
0
       error,
599
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
600
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
601
0
       "%s: unable to create parent file entry.",
602
0
       function );
603
604
0
      goto on_error;
605
0
    }
606
0
    inode  = NULL;
607
0
    result = 1;
608
0
  }
609
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
610
0
  if( libcthreads_read_write_lock_release_for_write(
611
0
       internal_file_entry->read_write_lock,
612
0
       error ) != 1 )
613
0
  {
614
0
    libcerror_error_set(
615
0
     error,
616
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
617
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
618
0
     "%s: unable to release read/write lock for writing.",
619
0
     function );
620
621
0
    return( -1 );
622
0
  }
623
0
#endif
624
0
  return( result );
625
626
0
on_error:
627
0
  if( inode != NULL )
628
0
  {
629
0
    libfsapfs_inode_free(
630
0
     &inode,
631
0
     NULL );
632
0
  }
633
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
634
0
  libcthreads_read_write_lock_release_for_write(
635
0
   internal_file_entry->read_write_lock,
636
0
   NULL );
637
0
#endif
638
0
  return( -1 );
639
0
}
640
641
/* Retrieves the creation date and time
642
 * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
643
 * This value is retrieved from the inode
644
 * Returns 1 if successful or -1 on error
645
 */
646
int libfsapfs_file_entry_get_creation_time(
647
     libfsapfs_file_entry_t *file_entry,
648
     int64_t *posix_time,
649
     libcerror_error_t **error )
650
616
{
651
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
652
616
  static char *function                                = "libfsapfs_file_entry_get_creation_time";
653
616
  int result                                           = 1;
654
655
616
  if( file_entry == NULL )
656
0
  {
657
0
    libcerror_error_set(
658
0
     error,
659
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
660
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
661
0
     "%s: invalid file entry.",
662
0
     function );
663
664
0
    return( -1 );
665
0
  }
666
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
667
668
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
669
616
  if( libcthreads_read_write_lock_grab_for_read(
670
616
       internal_file_entry->read_write_lock,
671
616
       error ) != 1 )
672
0
  {
673
0
    libcerror_error_set(
674
0
     error,
675
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
676
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
677
0
     "%s: unable to grab read/write lock for reading.",
678
0
     function );
679
680
0
    return( -1 );
681
0
  }
682
616
#endif
683
616
  if( libfsapfs_inode_get_creation_time(
684
616
       internal_file_entry->inode,
685
616
       posix_time,
686
616
       error ) != 1 )
687
0
  {
688
0
    libcerror_error_set(
689
0
     error,
690
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
691
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
692
0
     "%s: unable to retrieve creation time.",
693
0
     function );
694
695
0
    result = -1;
696
0
  }
697
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
698
616
  if( libcthreads_read_write_lock_release_for_read(
699
616
       internal_file_entry->read_write_lock,
700
616
       error ) != 1 )
701
0
  {
702
0
    libcerror_error_set(
703
0
     error,
704
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
705
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
706
0
     "%s: unable to release read/write lock for reading.",
707
0
     function );
708
709
0
    return( -1 );
710
0
  }
711
616
#endif
712
616
  return( result );
713
616
}
714
715
/* Retrieves the modification date and time
716
 * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
717
 * This value is retrieved from the inode
718
 * Returns 1 if successful or -1 on error
719
 */
720
int libfsapfs_file_entry_get_modification_time(
721
     libfsapfs_file_entry_t *file_entry,
722
     int64_t *posix_time,
723
     libcerror_error_t **error )
724
616
{
725
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
726
616
  static char *function                                = "libfsapfs_file_entry_get_modification_time";
727
616
  int result                                           = 1;
728
729
616
  if( file_entry == NULL )
730
0
  {
731
0
    libcerror_error_set(
732
0
     error,
733
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
734
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
735
0
     "%s: invalid file entry.",
736
0
     function );
737
738
0
    return( -1 );
739
0
  }
740
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
741
742
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
743
616
  if( libcthreads_read_write_lock_grab_for_read(
744
616
       internal_file_entry->read_write_lock,
745
616
       error ) != 1 )
746
0
  {
747
0
    libcerror_error_set(
748
0
     error,
749
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
750
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
751
0
     "%s: unable to grab read/write lock for reading.",
752
0
     function );
753
754
0
    return( -1 );
755
0
  }
756
616
#endif
757
616
  if( libfsapfs_inode_get_modification_time(
758
616
       internal_file_entry->inode,
759
616
       posix_time,
760
616
       error ) != 1 )
761
0
  {
762
0
    libcerror_error_set(
763
0
     error,
764
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
765
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
766
0
     "%s: unable to retrieve modification time.",
767
0
     function );
768
769
0
    result = -1;
770
0
  }
771
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
772
616
  if( libcthreads_read_write_lock_release_for_read(
773
616
       internal_file_entry->read_write_lock,
774
616
       error ) != 1 )
775
0
  {
776
0
    libcerror_error_set(
777
0
     error,
778
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
779
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
780
0
     "%s: unable to release read/write lock for reading.",
781
0
     function );
782
783
0
    return( -1 );
784
0
  }
785
616
#endif
786
616
  return( result );
787
616
}
788
789
/* Retrieves the access date and time
790
 * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
791
 * This value is retrieved from the inode
792
 * Returns 1 if successful or -1 on error
793
 */
794
int libfsapfs_file_entry_get_access_time(
795
     libfsapfs_file_entry_t *file_entry,
796
     int64_t *posix_time,
797
     libcerror_error_t **error )
798
616
{
799
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
800
616
  static char *function                                = "libfsapfs_file_entry_get_access_time";
801
616
  int result                                           = 1;
802
803
616
  if( file_entry == NULL )
804
0
  {
805
0
    libcerror_error_set(
806
0
     error,
807
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
808
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
809
0
     "%s: invalid file entry.",
810
0
     function );
811
812
0
    return( -1 );
813
0
  }
814
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
815
816
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
817
616
  if( libcthreads_read_write_lock_grab_for_read(
818
616
       internal_file_entry->read_write_lock,
819
616
       error ) != 1 )
820
0
  {
821
0
    libcerror_error_set(
822
0
     error,
823
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
824
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
825
0
     "%s: unable to grab read/write lock for reading.",
826
0
     function );
827
828
0
    return( -1 );
829
0
  }
830
616
#endif
831
616
  if( libfsapfs_inode_get_access_time(
832
616
       internal_file_entry->inode,
833
616
       posix_time,
834
616
       error ) != 1 )
835
0
  {
836
0
    libcerror_error_set(
837
0
     error,
838
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
839
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
840
0
     "%s: unable to retrieve access time.",
841
0
     function );
842
843
0
    result = -1;
844
0
  }
845
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
846
616
  if( libcthreads_read_write_lock_release_for_read(
847
616
       internal_file_entry->read_write_lock,
848
616
       error ) != 1 )
849
0
  {
850
0
    libcerror_error_set(
851
0
     error,
852
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
853
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
854
0
     "%s: unable to release read/write lock for reading.",
855
0
     function );
856
857
0
    return( -1 );
858
0
  }
859
616
#endif
860
616
  return( result );
861
616
}
862
863
/* Retrieves the inode change date and time
864
 * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
865
 * This value is retrieved from the inode
866
 * Returns 1 if successful or -1 on error
867
 */
868
int libfsapfs_file_entry_get_inode_change_time(
869
     libfsapfs_file_entry_t *file_entry,
870
     int64_t *posix_time,
871
     libcerror_error_t **error )
872
616
{
873
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
874
616
  static char *function                                = "libfsapfs_file_entry_get_inode_change_time";
875
616
  int result                                           = 1;
876
877
616
  if( file_entry == NULL )
878
0
  {
879
0
    libcerror_error_set(
880
0
     error,
881
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
882
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
883
0
     "%s: invalid file entry.",
884
0
     function );
885
886
0
    return( -1 );
887
0
  }
888
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
889
890
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
891
616
  if( libcthreads_read_write_lock_grab_for_read(
892
616
       internal_file_entry->read_write_lock,
893
616
       error ) != 1 )
894
0
  {
895
0
    libcerror_error_set(
896
0
     error,
897
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
898
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
899
0
     "%s: unable to grab read/write lock for reading.",
900
0
     function );
901
902
0
    return( -1 );
903
0
  }
904
616
#endif
905
616
  if( libfsapfs_inode_get_inode_change_time(
906
616
       internal_file_entry->inode,
907
616
       posix_time,
908
616
       error ) != 1 )
909
0
  {
910
0
    libcerror_error_set(
911
0
     error,
912
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
913
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
914
0
     "%s: unable to retrieve inode change time.",
915
0
     function );
916
917
0
    result = -1;
918
0
  }
919
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
920
616
  if( libcthreads_read_write_lock_release_for_read(
921
616
       internal_file_entry->read_write_lock,
922
616
       error ) != 1 )
923
0
  {
924
0
    libcerror_error_set(
925
0
     error,
926
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
927
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
928
0
     "%s: unable to release read/write lock for reading.",
929
0
     function );
930
931
0
    return( -1 );
932
0
  }
933
616
#endif
934
616
  return( result );
935
616
}
936
937
/* Retrieves the added date and time
938
 * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
939
 * This value is retrieved from the directory record
940
 * Returns 1 if successful, 0 if not available or -1 on error
941
 */
942
int libfsapfs_file_entry_get_added_time(
943
     libfsapfs_file_entry_t *file_entry,
944
     int64_t *posix_time,
945
     libcerror_error_t **error )
946
616
{
947
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
948
616
  static char *function                                = "libfsapfs_file_entry_get_added_time";
949
616
  int result                                           = 0;
950
951
616
  if( file_entry == NULL )
952
0
  {
953
0
    libcerror_error_set(
954
0
     error,
955
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
956
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
957
0
     "%s: invalid file entry.",
958
0
     function );
959
960
0
    return( -1 );
961
0
  }
962
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
963
964
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
965
616
  if( libcthreads_read_write_lock_grab_for_read(
966
616
       internal_file_entry->read_write_lock,
967
616
       error ) != 1 )
968
0
  {
969
0
    libcerror_error_set(
970
0
     error,
971
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
972
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
973
0
     "%s: unable to grab read/write lock for reading.",
974
0
     function );
975
976
0
    return( -1 );
977
0
  }
978
616
#endif
979
616
  if( internal_file_entry->directory_record != NULL )
980
616
  {
981
616
    result = libfsapfs_directory_record_get_added_time(
982
616
              internal_file_entry->directory_record,
983
616
              posix_time,
984
616
              error );
985
986
616
    if( result != 1 )
987
0
    {
988
0
      libcerror_error_set(
989
0
       error,
990
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
991
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
992
0
       "%s: unable to retrieve added time.",
993
0
       function );
994
995
0
      result = -1;
996
0
    }
997
616
  }
998
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
999
616
  if( libcthreads_read_write_lock_release_for_read(
1000
616
       internal_file_entry->read_write_lock,
1001
616
       error ) != 1 )
1002
0
  {
1003
0
    libcerror_error_set(
1004
0
     error,
1005
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1006
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1007
0
     "%s: unable to release read/write lock for reading.",
1008
0
     function );
1009
1010
0
    return( -1 );
1011
0
  }
1012
616
#endif
1013
616
  return( result );
1014
616
}
1015
1016
/* Retrieves the owner identifier
1017
 * This value is retrieved from the inode
1018
 * Returns 1 if successful or -1 on error
1019
 */
1020
int libfsapfs_file_entry_get_owner_identifier(
1021
     libfsapfs_file_entry_t *file_entry,
1022
     uint32_t *owner_identifier,
1023
     libcerror_error_t **error )
1024
616
{
1025
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1026
616
  static char *function                                = "libfsapfs_file_entry_get_owner_identifier";
1027
616
  int result                                           = 1;
1028
1029
616
  if( file_entry == NULL )
1030
0
  {
1031
0
    libcerror_error_set(
1032
0
     error,
1033
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1034
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1035
0
     "%s: invalid file entry.",
1036
0
     function );
1037
1038
0
    return( -1 );
1039
0
  }
1040
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1041
1042
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1043
616
  if( libcthreads_read_write_lock_grab_for_read(
1044
616
       internal_file_entry->read_write_lock,
1045
616
       error ) != 1 )
1046
0
  {
1047
0
    libcerror_error_set(
1048
0
     error,
1049
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1050
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1051
0
     "%s: unable to grab read/write lock for reading.",
1052
0
     function );
1053
1054
0
    return( -1 );
1055
0
  }
1056
616
#endif
1057
616
  if( libfsapfs_inode_get_owner_identifier(
1058
616
       internal_file_entry->inode,
1059
616
       owner_identifier,
1060
616
       error ) != 1 )
1061
0
  {
1062
0
    libcerror_error_set(
1063
0
     error,
1064
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1065
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1066
0
     "%s: unable to retrieve owner identifier.",
1067
0
     function );
1068
1069
0
    result = -1;
1070
0
  }
1071
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1072
616
  if( libcthreads_read_write_lock_release_for_read(
1073
616
       internal_file_entry->read_write_lock,
1074
616
       error ) != 1 )
1075
0
  {
1076
0
    libcerror_error_set(
1077
0
     error,
1078
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1079
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1080
0
     "%s: unable to release read/write lock for reading.",
1081
0
     function );
1082
1083
0
    return( -1 );
1084
0
  }
1085
616
#endif
1086
616
  return( result );
1087
616
}
1088
1089
/* Retrieves the group identifier
1090
 * This value is retrieved from the inode
1091
 * Returns 1 if successful or -1 on error
1092
 */
1093
int libfsapfs_file_entry_get_group_identifier(
1094
     libfsapfs_file_entry_t *file_entry,
1095
     uint32_t *group_identifier,
1096
     libcerror_error_t **error )
1097
616
{
1098
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1099
616
  static char *function                                = "libfsapfs_file_entry_get_group_identifier";
1100
616
  int result                                           = 1;
1101
1102
616
  if( file_entry == NULL )
1103
0
  {
1104
0
    libcerror_error_set(
1105
0
     error,
1106
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1107
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1108
0
     "%s: invalid file entry.",
1109
0
     function );
1110
1111
0
    return( -1 );
1112
0
  }
1113
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1114
1115
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1116
616
  if( libcthreads_read_write_lock_grab_for_read(
1117
616
       internal_file_entry->read_write_lock,
1118
616
       error ) != 1 )
1119
0
  {
1120
0
    libcerror_error_set(
1121
0
     error,
1122
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1123
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1124
0
     "%s: unable to grab read/write lock for reading.",
1125
0
     function );
1126
1127
0
    return( -1 );
1128
0
  }
1129
616
#endif
1130
616
  if( libfsapfs_inode_get_group_identifier(
1131
616
       internal_file_entry->inode,
1132
616
       group_identifier,
1133
616
       error ) != 1 )
1134
0
  {
1135
0
    libcerror_error_set(
1136
0
     error,
1137
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1138
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1139
0
     "%s: unable to retrieve group identifier.",
1140
0
     function );
1141
1142
0
    result = -1;
1143
0
  }
1144
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1145
616
  if( libcthreads_read_write_lock_release_for_read(
1146
616
       internal_file_entry->read_write_lock,
1147
616
       error ) != 1 )
1148
0
  {
1149
0
    libcerror_error_set(
1150
0
     error,
1151
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1152
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1153
0
     "%s: unable to release read/write lock for reading.",
1154
0
     function );
1155
1156
0
    return( -1 );
1157
0
  }
1158
616
#endif
1159
616
  return( result );
1160
616
}
1161
1162
/* Retrieves the device identifier
1163
 * This value is retrieved from the inode
1164
 * Returns 1 if successful, 0 if not available or -1 on error
1165
 */
1166
int libfsapfs_file_entry_get_device_identifier(
1167
     libfsapfs_file_entry_t *file_entry,
1168
     uint32_t *device_identifier,
1169
     libcerror_error_t **error )
1170
616
{
1171
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1172
616
  static char *function                                = "libfsapfs_file_entry_get_device_identifier";
1173
616
  int result                                           = 0;
1174
1175
616
  if( file_entry == NULL )
1176
0
  {
1177
0
    libcerror_error_set(
1178
0
     error,
1179
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1180
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1181
0
     "%s: invalid file entry.",
1182
0
     function );
1183
1184
0
    return( -1 );
1185
0
  }
1186
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1187
1188
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1189
616
  if( libcthreads_read_write_lock_grab_for_read(
1190
616
       internal_file_entry->read_write_lock,
1191
616
       error ) != 1 )
1192
0
  {
1193
0
    libcerror_error_set(
1194
0
     error,
1195
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1196
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1197
0
     "%s: unable to grab read/write lock for reading.",
1198
0
     function );
1199
1200
0
    return( -1 );
1201
0
  }
1202
616
#endif
1203
616
  result = libfsapfs_inode_get_device_identifier(
1204
616
            internal_file_entry->inode,
1205
616
            device_identifier,
1206
616
            error );
1207
1208
616
  if( result == -1 )
1209
0
  {
1210
0
    libcerror_error_set(
1211
0
     error,
1212
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1213
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1214
0
     "%s: unable to retrieve device identifier.",
1215
0
     function );
1216
1217
0
    result = -1;
1218
0
  }
1219
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1220
616
  if( libcthreads_read_write_lock_release_for_read(
1221
616
       internal_file_entry->read_write_lock,
1222
616
       error ) != 1 )
1223
0
  {
1224
0
    libcerror_error_set(
1225
0
     error,
1226
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1227
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1228
0
     "%s: unable to release read/write lock for reading.",
1229
0
     function );
1230
1231
0
    return( -1 );
1232
0
  }
1233
616
#endif
1234
616
  return( result );
1235
616
}
1236
1237
/* Retrieves the device number
1238
 * This value is retrieved from the inode
1239
 * Returns 1 if successful, 0 if not available or -1 on error
1240
 */
1241
int libfsapfs_file_entry_get_device_number(
1242
     libfsapfs_file_entry_t *file_entry,
1243
     uint32_t *major_device_number,
1244
     uint32_t *minor_device_number,
1245
     libcerror_error_t **error )
1246
616
{
1247
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1248
616
  static char *function                                = "libfsapfs_file_entry_get_device_number";
1249
616
  int result                                           = 0;
1250
1251
616
  if( file_entry == 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 file entry.",
1258
0
     function );
1259
1260
0
    return( -1 );
1261
0
  }
1262
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1263
1264
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1265
616
  if( libcthreads_read_write_lock_grab_for_read(
1266
616
       internal_file_entry->read_write_lock,
1267
616
       error ) != 1 )
1268
0
  {
1269
0
    libcerror_error_set(
1270
0
     error,
1271
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1272
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1273
0
     "%s: unable to grab read/write lock for reading.",
1274
0
     function );
1275
1276
0
    return( -1 );
1277
0
  }
1278
616
#endif
1279
616
  result = libfsapfs_inode_get_device_number(
1280
616
            internal_file_entry->inode,
1281
616
            major_device_number,
1282
616
            minor_device_number,
1283
616
            error );
1284
1285
616
  if( result == -1 )
1286
0
  {
1287
0
    libcerror_error_set(
1288
0
     error,
1289
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1290
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1291
0
     "%s: unable to retrieve device number.",
1292
0
     function );
1293
1294
0
    result = -1;
1295
0
  }
1296
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1297
616
  if( libcthreads_read_write_lock_release_for_read(
1298
616
       internal_file_entry->read_write_lock,
1299
616
       error ) != 1 )
1300
0
  {
1301
0
    libcerror_error_set(
1302
0
     error,
1303
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1304
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1305
0
     "%s: unable to release read/write lock for reading.",
1306
0
     function );
1307
1308
0
    return( -1 );
1309
0
  }
1310
616
#endif
1311
616
  return( result );
1312
616
}
1313
1314
/* Retrieves the file mode
1315
 * This value is retrieved from the inode
1316
 * Returns 1 if successful or -1 on error
1317
 */
1318
int libfsapfs_file_entry_get_file_mode(
1319
     libfsapfs_file_entry_t *file_entry,
1320
     uint16_t *file_mode,
1321
     libcerror_error_t **error )
1322
616
{
1323
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1324
616
  static char *function                                = "libfsapfs_file_entry_get_file_mode";
1325
616
  int result                                           = 1;
1326
1327
616
  if( file_entry == NULL )
1328
0
  {
1329
0
    libcerror_error_set(
1330
0
     error,
1331
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1332
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1333
0
     "%s: invalid file entry.",
1334
0
     function );
1335
1336
0
    return( -1 );
1337
0
  }
1338
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1339
1340
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1341
616
  if( libcthreads_read_write_lock_grab_for_read(
1342
616
       internal_file_entry->read_write_lock,
1343
616
       error ) != 1 )
1344
0
  {
1345
0
    libcerror_error_set(
1346
0
     error,
1347
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1348
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1349
0
     "%s: unable to grab read/write lock for reading.",
1350
0
     function );
1351
1352
0
    return( -1 );
1353
0
  }
1354
616
#endif
1355
616
  if( libfsapfs_inode_get_file_mode(
1356
616
       internal_file_entry->inode,
1357
616
       file_mode,
1358
616
       error ) != 1 )
1359
0
  {
1360
0
    libcerror_error_set(
1361
0
     error,
1362
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1363
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1364
0
     "%s: unable to retrieve file mode.",
1365
0
     function );
1366
1367
0
    result = -1;
1368
0
  }
1369
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1370
616
  if( libcthreads_read_write_lock_release_for_read(
1371
616
       internal_file_entry->read_write_lock,
1372
616
       error ) != 1 )
1373
0
  {
1374
0
    libcerror_error_set(
1375
0
     error,
1376
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1377
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1378
0
     "%s: unable to release read/write lock for reading.",
1379
0
     function );
1380
1381
0
    return( -1 );
1382
0
  }
1383
616
#endif
1384
616
  return( result );
1385
616
}
1386
1387
/* Retrieves the number of (hard) links (or children of a directory)
1388
 * This value is retrieved from the inode
1389
 * Returns 1 if successful or -1 on error
1390
 */
1391
int libfsapfs_file_entry_get_number_of_links(
1392
     libfsapfs_file_entry_t *file_entry,
1393
     uint32_t *number_of_links,
1394
     libcerror_error_t **error )
1395
616
{
1396
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1397
616
  static char *function                                = "libfsapfs_file_entry_get_number_of_links";
1398
616
  int result                                           = 1;
1399
1400
616
  if( file_entry == NULL )
1401
0
  {
1402
0
    libcerror_error_set(
1403
0
     error,
1404
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1405
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1406
0
     "%s: invalid file entry.",
1407
0
     function );
1408
1409
0
    return( -1 );
1410
0
  }
1411
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1412
1413
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1414
616
  if( libcthreads_read_write_lock_grab_for_read(
1415
616
       internal_file_entry->read_write_lock,
1416
616
       error ) != 1 )
1417
0
  {
1418
0
    libcerror_error_set(
1419
0
     error,
1420
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1421
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1422
0
     "%s: unable to grab read/write lock for reading.",
1423
0
     function );
1424
1425
0
    return( -1 );
1426
0
  }
1427
616
#endif
1428
616
  if( libfsapfs_inode_get_number_of_links(
1429
616
       internal_file_entry->inode,
1430
616
       number_of_links,
1431
616
       error ) != 1 )
1432
0
  {
1433
0
    libcerror_error_set(
1434
0
     error,
1435
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1436
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1437
0
     "%s: unable to retrieve number of links from inode.",
1438
0
     function );
1439
1440
0
    result = -1;
1441
0
  }
1442
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1443
616
  if( libcthreads_read_write_lock_release_for_read(
1444
616
       internal_file_entry->read_write_lock,
1445
616
       error ) != 1 )
1446
0
  {
1447
0
    libcerror_error_set(
1448
0
     error,
1449
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1450
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1451
0
     "%s: unable to release read/write lock for reading.",
1452
0
     function );
1453
1454
0
    return( -1 );
1455
0
  }
1456
616
#endif
1457
616
  return( result );
1458
616
}
1459
1460
/* Retrieves the size of the UTF-8 encoded name
1461
 * The returned size includes the end of string character
1462
 * This value is retrieved from the inode
1463
 * Returns 1 if successful or -1 on error
1464
 */
1465
int libfsapfs_file_entry_get_utf8_name_size(
1466
     libfsapfs_file_entry_t *file_entry,
1467
     size_t *utf8_string_size,
1468
     libcerror_error_t **error )
1469
616
{
1470
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1471
616
  static char *function                                = "libfsapfs_file_entry_get_utf8_name_size";
1472
616
  int result                                           = 1;
1473
1474
616
  if( file_entry == NULL )
1475
0
  {
1476
0
    libcerror_error_set(
1477
0
     error,
1478
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1479
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1480
0
     "%s: invalid file entry.",
1481
0
     function );
1482
1483
0
    return( -1 );
1484
0
  }
1485
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1486
1487
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1488
616
  if( libcthreads_read_write_lock_grab_for_read(
1489
616
       internal_file_entry->read_write_lock,
1490
616
       error ) != 1 )
1491
0
  {
1492
0
    libcerror_error_set(
1493
0
     error,
1494
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1495
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1496
0
     "%s: unable to grab read/write lock for reading.",
1497
0
     function );
1498
1499
0
    return( -1 );
1500
0
  }
1501
616
#endif
1502
616
  if( internal_file_entry->directory_record != NULL )
1503
616
  {
1504
616
    if( libfsapfs_directory_record_get_utf8_name_size(
1505
616
         internal_file_entry->directory_record,
1506
616
         utf8_string_size,
1507
616
         error ) != 1 )
1508
278
    {
1509
278
      libcerror_error_set(
1510
278
       error,
1511
278
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1512
278
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1513
278
       "%s: unable to retrieve UTF-8 string size from directory record.",
1514
278
       function );
1515
1516
278
      result = -1;
1517
278
    }
1518
616
  }
1519
0
  else
1520
0
  {
1521
0
    if( libfsapfs_inode_get_utf8_name_size(
1522
0
         internal_file_entry->inode,
1523
0
         utf8_string_size,
1524
0
         error ) != 1 )
1525
0
    {
1526
0
      libcerror_error_set(
1527
0
       error,
1528
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1529
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1530
0
       "%s: unable to retrieve UTF-8 string size from inode.",
1531
0
       function );
1532
1533
0
      result = -1;
1534
0
    }
1535
0
  }
1536
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1537
616
  if( libcthreads_read_write_lock_release_for_read(
1538
616
       internal_file_entry->read_write_lock,
1539
616
       error ) != 1 )
1540
0
  {
1541
0
    libcerror_error_set(
1542
0
     error,
1543
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1544
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1545
0
     "%s: unable to release read/write lock for reading.",
1546
0
     function );
1547
1548
0
    return( -1 );
1549
0
  }
1550
616
#endif
1551
616
  return( result );
1552
616
}
1553
1554
/* Retrieves the UTF-8 encoded name
1555
 * The size should include the end of string character
1556
 * This value is retrieved from the inode
1557
 * Returns 1 if successful or -1 on error
1558
 */
1559
int libfsapfs_file_entry_get_utf8_name(
1560
     libfsapfs_file_entry_t *file_entry,
1561
     uint8_t *utf8_string,
1562
     size_t utf8_string_size,
1563
     libcerror_error_t **error )
1564
616
{
1565
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1566
616
  static char *function                                = "libfsapfs_file_entry_get_utf8_name";
1567
616
  int result                                           = 1;
1568
1569
616
  if( file_entry == NULL )
1570
0
  {
1571
0
    libcerror_error_set(
1572
0
     error,
1573
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1574
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1575
0
     "%s: invalid file entry.",
1576
0
     function );
1577
1578
0
    return( -1 );
1579
0
  }
1580
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1581
1582
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1583
616
  if( libcthreads_read_write_lock_grab_for_read(
1584
616
       internal_file_entry->read_write_lock,
1585
616
       error ) != 1 )
1586
0
  {
1587
0
    libcerror_error_set(
1588
0
     error,
1589
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1590
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1591
0
     "%s: unable to grab read/write lock for reading.",
1592
0
     function );
1593
1594
0
    return( -1 );
1595
0
  }
1596
616
#endif
1597
616
  if( internal_file_entry->directory_record != NULL )
1598
616
  {
1599
616
    if( libfsapfs_directory_record_get_utf8_name(
1600
616
         internal_file_entry->directory_record,
1601
616
         utf8_string,
1602
616
         utf8_string_size,
1603
616
         error ) != 1 )
1604
278
    {
1605
278
      libcerror_error_set(
1606
278
       error,
1607
278
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1608
278
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1609
278
       "%s: unable to retrieve UTF-8 string from directory entry.",
1610
278
       function );
1611
1612
278
      result = -1;
1613
278
    }
1614
616
  }
1615
0
  else
1616
0
  {
1617
0
    if( libfsapfs_inode_get_utf8_name(
1618
0
         internal_file_entry->inode,
1619
0
         utf8_string,
1620
0
         utf8_string_size,
1621
0
         error ) != 1 )
1622
0
    {
1623
0
      libcerror_error_set(
1624
0
       error,
1625
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1626
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1627
0
       "%s: unable to retrieve UTF-8 string from inode.",
1628
0
       function );
1629
1630
0
      result = -1;
1631
0
    }
1632
0
  }
1633
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1634
616
  if( libcthreads_read_write_lock_release_for_read(
1635
616
       internal_file_entry->read_write_lock,
1636
616
       error ) != 1 )
1637
0
  {
1638
0
    libcerror_error_set(
1639
0
     error,
1640
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1641
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1642
0
     "%s: unable to release read/write lock for reading.",
1643
0
     function );
1644
1645
0
    return( -1 );
1646
0
  }
1647
616
#endif
1648
616
  return( result );
1649
616
}
1650
1651
/* Retrieves the size of the UTF-16 encoded name
1652
 * The returned size includes the end of string character
1653
 * This value is retrieved from the inode
1654
 * Returns 1 if successful or -1 on error
1655
 */
1656
int libfsapfs_file_entry_get_utf16_name_size(
1657
     libfsapfs_file_entry_t *file_entry,
1658
     size_t *utf16_string_size,
1659
     libcerror_error_t **error )
1660
0
{
1661
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1662
0
  static char *function                                = "libfsapfs_file_entry_get_utf16_name_size";
1663
0
  int result                                           = 1;
1664
1665
0
  if( file_entry == NULL )
1666
0
  {
1667
0
    libcerror_error_set(
1668
0
     error,
1669
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1670
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1671
0
     "%s: invalid file entry.",
1672
0
     function );
1673
1674
0
    return( -1 );
1675
0
  }
1676
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1677
1678
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1679
0
  if( libcthreads_read_write_lock_grab_for_read(
1680
0
       internal_file_entry->read_write_lock,
1681
0
       error ) != 1 )
1682
0
  {
1683
0
    libcerror_error_set(
1684
0
     error,
1685
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1686
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1687
0
     "%s: unable to grab read/write lock for reading.",
1688
0
     function );
1689
1690
0
    return( -1 );
1691
0
  }
1692
0
#endif
1693
0
  if( internal_file_entry->directory_record != NULL )
1694
0
  {
1695
0
    if( libfsapfs_directory_record_get_utf16_name_size(
1696
0
         internal_file_entry->directory_record,
1697
0
         utf16_string_size,
1698
0
         error ) != 1 )
1699
0
    {
1700
0
      libcerror_error_set(
1701
0
       error,
1702
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1703
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1704
0
       "%s: unable to retrieve UTF-16 string size from directory record.",
1705
0
       function );
1706
1707
0
      result = -1;
1708
0
    }
1709
0
  }
1710
0
  else
1711
0
  {
1712
0
    if( libfsapfs_inode_get_utf16_name_size(
1713
0
         internal_file_entry->inode,
1714
0
         utf16_string_size,
1715
0
         error ) != 1 )
1716
0
    {
1717
0
      libcerror_error_set(
1718
0
       error,
1719
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1720
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1721
0
       "%s: unable to retrieve UTF-16 string size from inode.",
1722
0
       function );
1723
1724
0
      result = -1;
1725
0
    }
1726
0
  }
1727
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1728
0
  if( libcthreads_read_write_lock_release_for_read(
1729
0
       internal_file_entry->read_write_lock,
1730
0
       error ) != 1 )
1731
0
  {
1732
0
    libcerror_error_set(
1733
0
     error,
1734
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1735
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1736
0
     "%s: unable to release read/write lock for reading.",
1737
0
     function );
1738
1739
0
    return( -1 );
1740
0
  }
1741
0
#endif
1742
0
  return( result );
1743
0
}
1744
1745
/* Retrieves the UTF-16 encoded name
1746
 * The size should include the end of string character
1747
 * This value is retrieved from the inode
1748
 * Returns 1 if successful or -1 on error
1749
 */
1750
int libfsapfs_file_entry_get_utf16_name(
1751
     libfsapfs_file_entry_t *file_entry,
1752
     uint16_t *utf16_string,
1753
     size_t utf16_string_size,
1754
     libcerror_error_t **error )
1755
0
{
1756
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1757
0
  static char *function                                = "libfsapfs_file_entry_get_utf16_name";
1758
0
  int result                                           = 1;
1759
1760
0
  if( file_entry == NULL )
1761
0
  {
1762
0
    libcerror_error_set(
1763
0
     error,
1764
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1765
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1766
0
     "%s: invalid file entry.",
1767
0
     function );
1768
1769
0
    return( -1 );
1770
0
  }
1771
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1772
1773
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1774
0
  if( libcthreads_read_write_lock_grab_for_read(
1775
0
       internal_file_entry->read_write_lock,
1776
0
       error ) != 1 )
1777
0
  {
1778
0
    libcerror_error_set(
1779
0
     error,
1780
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1781
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1782
0
     "%s: unable to grab read/write lock for reading.",
1783
0
     function );
1784
1785
0
    return( -1 );
1786
0
  }
1787
0
#endif
1788
0
  if( internal_file_entry->directory_record != NULL )
1789
0
  {
1790
0
    if( libfsapfs_directory_record_get_utf16_name(
1791
0
         internal_file_entry->directory_record,
1792
0
         utf16_string,
1793
0
         utf16_string_size,
1794
0
         error ) != 1 )
1795
0
    {
1796
0
      libcerror_error_set(
1797
0
       error,
1798
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1799
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1800
0
       "%s: unable to retrieve UTF-16 string from directory record.",
1801
0
       function );
1802
1803
0
      result = -1;
1804
0
    }
1805
0
  }
1806
0
  else
1807
0
  {
1808
0
    if( libfsapfs_inode_get_utf16_name(
1809
0
         internal_file_entry->inode,
1810
0
         utf16_string,
1811
0
         utf16_string_size,
1812
0
         error ) != 1 )
1813
0
    {
1814
0
      libcerror_error_set(
1815
0
       error,
1816
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1817
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1818
0
       "%s: unable to retrieve UTF-16 string from inode.",
1819
0
       function );
1820
1821
0
      result = -1;
1822
0
    }
1823
0
  }
1824
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1825
0
  if( libcthreads_read_write_lock_release_for_read(
1826
0
       internal_file_entry->read_write_lock,
1827
0
       error ) != 1 )
1828
0
  {
1829
0
    libcerror_error_set(
1830
0
     error,
1831
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1832
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1833
0
     "%s: unable to release read/write lock for reading.",
1834
0
     function );
1835
1836
0
    return( -1 );
1837
0
  }
1838
0
#endif
1839
0
  return( result );
1840
0
}
1841
1842
/* Determines the extended attributes
1843
 * Returns 1 if successful or -1 on error
1844
 */
1845
int libfsapfs_internal_file_entry_get_extended_attributes(
1846
     libfsapfs_internal_file_entry_t *internal_file_entry,
1847
     libcerror_error_t **error )
1848
1.20k
{
1849
1.20k
  libfsapfs_attribute_values_t *attribute_values = NULL;
1850
1.20k
  static char *function                          = "libfsapfs_internal_file_entry_get_extended_attributes";
1851
1.20k
  uint64_t file_system_identifier                = 0;
1852
1.20k
  int attribute_index                            = 0;
1853
1.20k
  int number_of_attributes                       = 0;
1854
1.20k
  int result                                     = 0;
1855
1856
1.20k
  if( internal_file_entry == NULL )
1857
0
  {
1858
0
    libcerror_error_set(
1859
0
     error,
1860
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1861
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1862
0
     "%s: invalid file entry.",
1863
0
     function );
1864
1865
0
    return( -1 );
1866
0
  }
1867
1.20k
  if( internal_file_entry->extended_attributes_array != NULL )
1868
0
  {
1869
0
    libcerror_error_set(
1870
0
     error,
1871
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1872
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1873
0
     "%s: invalid file entry - extended attributes value already set.",
1874
0
     function );
1875
1876
0
    return( -1 );
1877
0
  }
1878
1.20k
  if( libfsapfs_inode_get_identifier(
1879
1.20k
       internal_file_entry->inode,
1880
1.20k
       &file_system_identifier,
1881
1.20k
       error ) != 1 )
1882
0
  {
1883
0
    libcerror_error_set(
1884
0
     error,
1885
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1886
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1887
0
     "%s: unable to retrieve identifier from inode.",
1888
0
     function );
1889
1890
0
    goto on_error;
1891
0
  }
1892
1.20k
  if( libcdata_array_initialize(
1893
1.20k
       &( internal_file_entry->extended_attributes_array ),
1894
1.20k
       0,
1895
1.20k
       error ) != 1 )
1896
0
  {
1897
0
    libcerror_error_set(
1898
0
     error,
1899
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1900
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1901
0
     "%s: unable to create extended attributes array.",
1902
0
     function );
1903
1904
0
    goto on_error;
1905
0
  }
1906
1.20k
  result = libfsapfs_file_system_btree_get_attributes(
1907
1.20k
      internal_file_entry->file_system_btree,
1908
1.20k
      internal_file_entry->file_io_handle,
1909
1.20k
      file_system_identifier,
1910
1.20k
      internal_file_entry->transaction_identifier,
1911
1.20k
      internal_file_entry->extended_attributes_array,
1912
1.20k
      error );
1913
1914
1.20k
  if( result == -1 )
1915
395
  {
1916
395
    libcerror_error_set(
1917
395
     error,
1918
395
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1919
395
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1920
395
     "%s: unable to retrieve attributes from file system B-tree.",
1921
395
     function );
1922
1923
395
    goto on_error;
1924
395
  }
1925
806
  if( libcdata_array_get_number_of_entries(
1926
806
       internal_file_entry->extended_attributes_array,
1927
806
       &number_of_attributes,
1928
806
       error ) != 1 )
1929
0
  {
1930
0
    libcerror_error_set(
1931
0
     error,
1932
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1933
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1934
0
     "%s: unable to retrieve number of entries from extended attributes array.",
1935
0
     function );
1936
1937
0
    goto on_error;
1938
0
  }
1939
806
  for( attribute_index = 0;
1940
1.09k
       attribute_index < number_of_attributes;
1941
806
       attribute_index++ )
1942
460
  {
1943
460
    if( libcdata_array_get_entry_by_index(
1944
460
         internal_file_entry->extended_attributes_array,
1945
460
         attribute_index,
1946
460
         (intptr_t **) &attribute_values,
1947
460
         error ) != 1 )
1948
0
    {
1949
0
      libcerror_error_set(
1950
0
       error,
1951
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1952
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1953
0
       "%s: unable to retrieve attribute: %d values.",
1954
0
       function,
1955
0
       attribute_index );
1956
1957
0
      goto on_error;
1958
0
    }
1959
460
    result = libfsapfs_attribute_values_compare_name_with_utf8_string(
1960
460
              attribute_values,
1961
460
              (uint8_t *) "com.apple.decmpfs",
1962
460
              17,
1963
460
              error );
1964
1965
460
    if( result == -1 )
1966
158
    {
1967
158
      libcerror_error_set(
1968
158
       error,
1969
158
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1970
158
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1971
158
       "%s: unable to compare UTF-8 string with name of extended attribute.",
1972
158
       function );
1973
1974
158
      goto on_error;
1975
158
    }
1976
302
    else if( result == LIBUNA_COMPARE_EQUAL )
1977
0
    {
1978
0
      internal_file_entry->compressed_data_attribute_values = attribute_values;
1979
1980
0
      continue;
1981
0
    }
1982
302
    result = libfsapfs_attribute_values_compare_name_with_utf8_string(
1983
302
              attribute_values,
1984
302
              (uint8_t *) "com.apple.ResourceFork",
1985
302
              22,
1986
302
              error );
1987
1988
302
    if( result == -1 )
1989
6
    {
1990
6
      libcerror_error_set(
1991
6
       error,
1992
6
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1993
6
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1994
6
       "%s: unable to compare UTF-8 string with name of extended attribute.",
1995
6
       function );
1996
1997
6
      goto on_error;
1998
6
    }
1999
296
    else if( result == LIBUNA_COMPARE_EQUAL )
2000
13
    {
2001
13
      internal_file_entry->resource_fork_attribute_values = attribute_values;
2002
2003
13
      continue;
2004
13
    }
2005
283
    result = libfsapfs_attribute_values_compare_name_with_utf8_string(
2006
283
              attribute_values,
2007
283
              (uint8_t *) "com.apple.fs.symlink",
2008
283
              20,
2009
283
              error );
2010
2011
283
    if( result == -1 )
2012
5
    {
2013
5
      libcerror_error_set(
2014
5
       error,
2015
5
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2016
5
       LIBCERROR_RUNTIME_ERROR_GENERIC,
2017
5
       "%s: unable to compare UTF-8 string with name of extended attribute.",
2018
5
       function );
2019
2020
5
      goto on_error;
2021
5
    }
2022
278
    else if( result == LIBUNA_COMPARE_EQUAL )
2023
11
    {
2024
11
      internal_file_entry->symbolic_link_attribute_values = attribute_values;
2025
2026
11
      continue;
2027
11
    }
2028
283
  }
2029
637
  return( 1 );
2030
2031
564
on_error:
2032
564
  if( internal_file_entry->extended_attributes_array != NULL )
2033
564
  {
2034
564
    libcdata_array_free(
2035
564
     &( internal_file_entry->extended_attributes_array ),
2036
564
     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_attribute_values_free,
2037
564
     NULL );
2038
564
  }
2039
564
  return( -1 );
2040
806
}
2041
2042
/* Determines the symbolic link data
2043
 * Returns 1 if successful or -1 on error
2044
 */
2045
int libfsapfs_internal_file_entry_get_symbolic_link_data(
2046
     libfsapfs_internal_file_entry_t *internal_file_entry,
2047
     libcerror_error_t **error )
2048
1.22k
{
2049
1.22k
  libfdata_stream_t *data_stream = NULL;
2050
1.22k
  static char *function          = "libfsapfs_internal_file_entry_get_symbolic_link_data";
2051
1.22k
  size_t symbolic_link_data_size = 0;
2052
1.22k
  ssize_t read_count             = 0;
2053
2054
1.22k
  if( internal_file_entry == NULL )
2055
0
  {
2056
0
    libcerror_error_set(
2057
0
     error,
2058
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2059
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2060
0
     "%s: invalid file entry.",
2061
0
     function );
2062
2063
0
    return( -1 );
2064
0
  }
2065
1.22k
  if( internal_file_entry->symbolic_link_data != NULL )
2066
0
  {
2067
0
    libcerror_error_set(
2068
0
     error,
2069
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2070
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2071
0
     "%s: invalid file entry - symbolic link data value already set.",
2072
0
     function );
2073
2074
0
    return( -1 );
2075
0
  }
2076
1.22k
  if( internal_file_entry->extended_attributes_array == NULL )
2077
730
  {
2078
730
    if( libfsapfs_internal_file_entry_get_extended_attributes(
2079
730
         internal_file_entry,
2080
730
         error ) != 1 )
2081
228
    {
2082
228
      libcerror_error_set(
2083
228
       error,
2084
228
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2085
228
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2086
228
       "%s: unable to determine extended attributes.",
2087
228
       function );
2088
2089
228
      goto on_error;
2090
228
    }
2091
730
  }
2092
999
  if( internal_file_entry->symbolic_link_attribute_values != NULL )
2093
7
  {
2094
7
    if( ( internal_file_entry->symbolic_link_attribute_values->value_data_size == 0 )
2095
5
     || ( internal_file_entry->symbolic_link_attribute_values->value_data_size > (size64_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
2096
2
    {
2097
2
      libcerror_error_set(
2098
2
       error,
2099
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2100
2
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2101
2
       "%s: invalid internal file entry - invalid symbolic link attribute values - value data size value out of bounds.",
2102
2
       function );
2103
2104
2
      goto on_error;
2105
2
    }
2106
5
    symbolic_link_data_size = (size_t) internal_file_entry->symbolic_link_attribute_values->value_data_size;
2107
2108
5
    internal_file_entry->symbolic_link_data = (uint8_t *) memory_allocate(
2109
5
                                                           sizeof( uint8_t ) * symbolic_link_data_size );
2110
2111
5
    if( internal_file_entry->symbolic_link_data == NULL )
2112
0
    {
2113
0
      libcerror_error_set(
2114
0
       error,
2115
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2116
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2117
0
       "%s: unable to create symbolic link data.",
2118
0
       function );
2119
2120
0
      goto on_error;
2121
0
    }
2122
5
    internal_file_entry->symbolic_link_data_size = symbolic_link_data_size;
2123
2124
5
    if( libfsapfs_attributes_get_data_stream(
2125
5
         internal_file_entry->symbolic_link_attribute_values,
2126
5
         internal_file_entry->io_handle,
2127
5
         internal_file_entry->file_io_handle,
2128
5
         internal_file_entry->encryption_context,
2129
5
         internal_file_entry->file_system_btree,
2130
5
         internal_file_entry->transaction_identifier,
2131
5
         &data_stream,
2132
5
         error ) != 1 )
2133
0
    {
2134
0
      libcerror_error_set(
2135
0
       error,
2136
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2137
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2138
0
       "%s: unable to retrieve data stream for symbolic link extended attribute.",
2139
0
       function );
2140
2141
0
      goto on_error;
2142
0
    }
2143
5
    read_count = libfdata_stream_read_buffer_at_offset(
2144
5
                  data_stream,
2145
5
                  (intptr_t *) internal_file_entry->file_io_handle,
2146
5
                  internal_file_entry->symbolic_link_data,
2147
5
                  internal_file_entry->symbolic_link_data_size,
2148
5
                  0,
2149
5
                  0,
2150
5
                  error );
2151
         
2152
5
    if( read_count != (ssize_t) internal_file_entry->symbolic_link_data_size )
2153
0
    {
2154
0
      libcerror_error_set(
2155
0
       error,
2156
0
       LIBCERROR_ERROR_DOMAIN_IO,
2157
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2158
0
       "%s: unable to read symbolic link data.",
2159
0
       function );
2160
2161
0
      goto on_error;
2162
0
    }
2163
5
    if( libfdata_stream_free(
2164
5
         &data_stream,
2165
5
         error ) != 1 )
2166
0
    {
2167
0
      libcerror_error_set(
2168
0
       error,
2169
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2170
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2171
0
       "%s: unable to free symbolic link data stream.",
2172
0
       function );
2173
2174
0
      goto on_error;
2175
0
    }
2176
5
  }
2177
997
  return( 1 );
2178
2179
230
on_error:
2180
230
  if( data_stream != NULL )
2181
0
  {
2182
0
    libfdata_stream_free(
2183
0
     &data_stream,
2184
0
     NULL );
2185
0
  }
2186
230
  if( internal_file_entry->symbolic_link_data != NULL )
2187
0
  {
2188
0
    memory_free(
2189
0
     internal_file_entry->symbolic_link_data );
2190
2191
0
    internal_file_entry->symbolic_link_data = NULL;
2192
0
  }
2193
230
  internal_file_entry->symbolic_link_data_size = 0;
2194
2195
230
  return( -1 );
2196
999
}
2197
2198
/* Retrieves the size of the UTF-8 encoded symbolic link target
2199
 * The size should include the end of string character
2200
 * This value is retrieved from the com.apple.fs.symlink extended attribute
2201
 * Returns 1 if successful, 0 if not available or -1 on error
2202
 */
2203
int libfsapfs_file_entry_get_utf8_symbolic_link_target_size(
2204
     libfsapfs_file_entry_t *file_entry,
2205
     size_t *utf8_string_size,
2206
     libcerror_error_t **error )
2207
616
{
2208
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2209
616
  static char *function                                = "libfsapfs_file_entry_get_utf8_symbolic_link_target_size";
2210
616
  int result                                           = 0;
2211
2212
616
  if( file_entry == NULL )
2213
0
  {
2214
0
    libcerror_error_set(
2215
0
     error,
2216
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2217
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2218
0
     "%s: invalid file entry.",
2219
0
     function );
2220
2221
0
    return( -1 );
2222
0
  }
2223
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2224
2225
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2226
616
  if( libcthreads_read_write_lock_grab_for_write(
2227
616
       internal_file_entry->read_write_lock,
2228
616
       error ) != 1 )
2229
0
  {
2230
0
    libcerror_error_set(
2231
0
     error,
2232
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2233
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2234
0
     "%s: unable to grab read/write lock for writing.",
2235
0
     function );
2236
2237
0
    return( -1 );
2238
0
  }
2239
616
#endif
2240
616
  if( internal_file_entry->symbolic_link_data == NULL )
2241
616
  {
2242
616
    if( libfsapfs_internal_file_entry_get_symbolic_link_data(
2243
616
         internal_file_entry,
2244
616
         error ) != 1 )
2245
115
    {
2246
115
      libcerror_error_set(
2247
115
       error,
2248
115
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2249
115
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2250
115
       "%s: unable to determine symbolic link data.",
2251
115
       function );
2252
2253
115
      goto on_error;
2254
115
    }
2255
616
  }
2256
501
  if( internal_file_entry->symbolic_link_data != NULL )
2257
5
  {
2258
5
    if( libuna_utf8_string_size_from_utf8_stream(
2259
5
         internal_file_entry->symbolic_link_data,
2260
5
         internal_file_entry->symbolic_link_data_size,
2261
5
         utf8_string_size,
2262
5
         error ) != 1 )
2263
2
    {
2264
2
      libcerror_error_set(
2265
2
       error,
2266
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2267
2
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2268
2
       "%s: unable to retrieve UTF-8 string size.",
2269
2
       function );
2270
2271
2
      goto on_error;
2272
2
    }
2273
3
    result = 1;
2274
3
  }
2275
499
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2276
499
  if( libcthreads_read_write_lock_release_for_write(
2277
499
       internal_file_entry->read_write_lock,
2278
499
       error ) != 1 )
2279
0
  {
2280
0
    libcerror_error_set(
2281
0
     error,
2282
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2283
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2284
0
     "%s: unable to release read/write lock for writing.",
2285
0
     function );
2286
2287
0
    return( -1 );
2288
0
  }
2289
499
#endif
2290
499
  return( result );
2291
2292
117
on_error:
2293
117
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2294
117
  libcthreads_read_write_lock_release_for_write(
2295
117
   internal_file_entry->read_write_lock,
2296
117
   NULL );
2297
117
#endif
2298
117
  return( -1 );
2299
499
}
2300
2301
/* Retrieves the UTF-8 encoded symbolic link target
2302
 * The size should include the end of string character
2303
 * This value is retrieved from the com.apple.fs.symlink extended attribute
2304
 * Returns 1 if successful, 0 if not available or -1 on error
2305
 */
2306
int libfsapfs_file_entry_get_utf8_symbolic_link_target(
2307
     libfsapfs_file_entry_t *file_entry,
2308
     uint8_t *utf8_string,
2309
     size_t utf8_string_size,
2310
     libcerror_error_t **error )
2311
616
{
2312
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2313
616
  static char *function                                = "libfsapfs_file_entry_get_utf8_symbolic_link_target";
2314
616
  int result                                           = 0;
2315
2316
616
  if( file_entry == NULL )
2317
0
  {
2318
0
    libcerror_error_set(
2319
0
     error,
2320
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2321
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2322
0
     "%s: invalid file entry.",
2323
0
     function );
2324
2325
0
    return( -1 );
2326
0
  }
2327
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2328
2329
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2330
616
  if( libcthreads_read_write_lock_grab_for_write(
2331
616
       internal_file_entry->read_write_lock,
2332
616
       error ) != 1 )
2333
0
  {
2334
0
    libcerror_error_set(
2335
0
     error,
2336
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2337
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2338
0
     "%s: unable to grab read/write lock for writing.",
2339
0
     function );
2340
2341
0
    return( -1 );
2342
0
  }
2343
616
#endif
2344
616
  if( internal_file_entry->symbolic_link_data == NULL )
2345
611
  {
2346
611
    if( libfsapfs_internal_file_entry_get_symbolic_link_data(
2347
611
         internal_file_entry,
2348
611
         error ) != 1 )
2349
115
    {
2350
115
      libcerror_error_set(
2351
115
       error,
2352
115
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2353
115
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2354
115
       "%s: unable to determine symbolic link data.",
2355
115
       function );
2356
2357
115
      goto on_error;
2358
115
    }
2359
611
  }
2360
501
  if( internal_file_entry->symbolic_link_data != NULL )
2361
5
  {
2362
5
    if( libuna_utf8_string_copy_from_utf8_stream(
2363
5
         utf8_string,
2364
5
         utf8_string_size,
2365
5
         internal_file_entry->symbolic_link_data,
2366
5
         internal_file_entry->symbolic_link_data_size,
2367
5
         error ) != 1 )
2368
2
    {
2369
2
      libcerror_error_set(
2370
2
       error,
2371
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2372
2
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2373
2
       "%s: unable to retrieve UTF-8 string.",
2374
2
       function );
2375
2376
2
      goto on_error;
2377
2
    }
2378
3
    result = 1;
2379
3
  }
2380
499
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2381
499
  if( libcthreads_read_write_lock_release_for_write(
2382
499
       internal_file_entry->read_write_lock,
2383
499
       error ) != 1 )
2384
0
  {
2385
0
    libcerror_error_set(
2386
0
     error,
2387
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2388
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2389
0
     "%s: unable to release read/write lock for writing.",
2390
0
     function );
2391
2392
0
    return( -1 );
2393
0
  }
2394
499
#endif
2395
499
  return( result );
2396
2397
117
on_error:
2398
117
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2399
117
  libcthreads_read_write_lock_release_for_write(
2400
117
   internal_file_entry->read_write_lock,
2401
117
   NULL );
2402
117
#endif
2403
117
  return( -1 );
2404
499
}
2405
2406
/* Retrieves the size of the UTF-16 encoded symbolic link target
2407
 * The size should include the end of string character
2408
 * This value is retrieved from the com.apple.fs.symlink extended attribute
2409
 * Returns 1 if successful, 0 if not available or -1 on error
2410
 */
2411
int libfsapfs_file_entry_get_utf16_symbolic_link_target_size(
2412
     libfsapfs_file_entry_t *file_entry,
2413
     size_t *utf16_string_size,
2414
     libcerror_error_t **error )
2415
0
{
2416
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2417
0
  static char *function                                = "libfsapfs_file_entry_get_utf16_symbolic_link_target_size";
2418
0
  int result                                           = 0;
2419
2420
0
  if( file_entry == NULL )
2421
0
  {
2422
0
    libcerror_error_set(
2423
0
     error,
2424
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2425
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2426
0
     "%s: invalid file entry.",
2427
0
     function );
2428
2429
0
    return( -1 );
2430
0
  }
2431
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2432
2433
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2434
0
  if( libcthreads_read_write_lock_grab_for_write(
2435
0
       internal_file_entry->read_write_lock,
2436
0
       error ) != 1 )
2437
0
  {
2438
0
    libcerror_error_set(
2439
0
     error,
2440
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2441
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2442
0
     "%s: unable to grab read/write lock for writing.",
2443
0
     function );
2444
2445
0
    return( -1 );
2446
0
  }
2447
0
#endif
2448
0
  if( internal_file_entry->symbolic_link_data == NULL )
2449
0
  {
2450
0
    if( libfsapfs_internal_file_entry_get_symbolic_link_data(
2451
0
         internal_file_entry,
2452
0
         error ) != 1 )
2453
0
    {
2454
0
      libcerror_error_set(
2455
0
       error,
2456
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2457
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2458
0
       "%s: unable to determine symbolic link data.",
2459
0
       function );
2460
2461
0
      goto on_error;
2462
0
    }
2463
0
  }
2464
0
  if( internal_file_entry->symbolic_link_data != NULL )
2465
0
  {
2466
0
    if( libuna_utf16_string_size_from_utf8_stream(
2467
0
         internal_file_entry->symbolic_link_data,
2468
0
         internal_file_entry->symbolic_link_data_size,
2469
0
         utf16_string_size,
2470
0
         error ) != 1 )
2471
0
    {
2472
0
      libcerror_error_set(
2473
0
       error,
2474
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2475
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2476
0
       "%s: unable to retrieve UTF-16 string size.",
2477
0
       function );
2478
2479
0
      goto on_error;
2480
0
    }
2481
0
    result = 1;
2482
0
  }
2483
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2484
0
  if( libcthreads_read_write_lock_release_for_write(
2485
0
       internal_file_entry->read_write_lock,
2486
0
       error ) != 1 )
2487
0
  {
2488
0
    libcerror_error_set(
2489
0
     error,
2490
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2491
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2492
0
     "%s: unable to release read/write lock for writing.",
2493
0
     function );
2494
2495
0
    return( -1 );
2496
0
  }
2497
0
#endif
2498
0
  return( result );
2499
2500
0
on_error:
2501
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2502
0
  libcthreads_read_write_lock_release_for_write(
2503
0
   internal_file_entry->read_write_lock,
2504
0
   NULL );
2505
0
#endif
2506
0
  return( -1 );
2507
0
}
2508
2509
/* Retrieves the UTF-16 encoded symbolic link target
2510
 * The size should include the end of string character
2511
 * This value is retrieved from the com.apple.fs.symlink extended attribute
2512
 * Returns 1 if successful, 0 if not available or -1 on error
2513
 */
2514
int libfsapfs_file_entry_get_utf16_symbolic_link_target(
2515
     libfsapfs_file_entry_t *file_entry,
2516
     uint16_t *utf16_string,
2517
     size_t utf16_string_size,
2518
     libcerror_error_t **error )
2519
0
{
2520
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2521
0
  static char *function                                = "libfsapfs_file_entry_get_utf16_symbolic_link_target";
2522
0
  int result                                           = 0;
2523
2524
0
  if( file_entry == NULL )
2525
0
  {
2526
0
    libcerror_error_set(
2527
0
     error,
2528
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2529
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2530
0
     "%s: invalid file entry.",
2531
0
     function );
2532
2533
0
    return( -1 );
2534
0
  }
2535
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2536
2537
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2538
0
  if( libcthreads_read_write_lock_grab_for_write(
2539
0
       internal_file_entry->read_write_lock,
2540
0
       error ) != 1 )
2541
0
  {
2542
0
    libcerror_error_set(
2543
0
     error,
2544
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2545
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2546
0
     "%s: unable to grab read/write lock for writing.",
2547
0
     function );
2548
2549
0
    return( -1 );
2550
0
  }
2551
0
#endif
2552
0
  if( internal_file_entry->symbolic_link_data == NULL )
2553
0
  {
2554
0
    if( libfsapfs_internal_file_entry_get_symbolic_link_data(
2555
0
         internal_file_entry,
2556
0
         error ) != 1 )
2557
0
    {
2558
0
      libcerror_error_set(
2559
0
       error,
2560
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2561
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2562
0
       "%s: unable to determine symbolic link data.",
2563
0
       function );
2564
2565
0
      goto on_error;
2566
0
    }
2567
0
  }
2568
0
  if( internal_file_entry->symbolic_link_data != NULL )
2569
0
  {
2570
0
    if( libuna_utf16_string_copy_from_utf8_stream(
2571
0
         utf16_string,
2572
0
         utf16_string_size,
2573
0
         internal_file_entry->symbolic_link_data,
2574
0
         internal_file_entry->symbolic_link_data_size,
2575
0
         error ) != 1 )
2576
0
    {
2577
0
      libcerror_error_set(
2578
0
       error,
2579
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2580
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2581
0
       "%s: unable to retrieve UTF-16 string.",
2582
0
       function );
2583
2584
0
      goto on_error;
2585
0
    }
2586
0
    result = 1;
2587
0
  }
2588
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2589
0
  if( libcthreads_read_write_lock_release_for_write(
2590
0
       internal_file_entry->read_write_lock,
2591
0
       error ) != 1 )
2592
0
  {
2593
0
    libcerror_error_set(
2594
0
     error,
2595
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2596
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2597
0
     "%s: unable to release read/write lock for writing.",
2598
0
     function );
2599
2600
0
    return( -1 );
2601
0
  }
2602
0
#endif
2603
0
  return( result );
2604
2605
0
on_error:
2606
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2607
0
  libcthreads_read_write_lock_release_for_write(
2608
0
   internal_file_entry->read_write_lock,
2609
0
   NULL );
2610
0
#endif
2611
0
  return( -1 );
2612
0
}
2613
2614
/* Retrieves the number of extended attributes
2615
 * Returns 1 if successful or -1 on error
2616
 */
2617
int libfsapfs_file_entry_get_number_of_extended_attributes(
2618
     libfsapfs_file_entry_t *file_entry,
2619
     int *number_of_extended_attributes,
2620
     libcerror_error_t **error )
2621
243
{
2622
243
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2623
243
  static char *function                                = "libfsapfs_file_entry_get_number_of_extended_attributes";
2624
243
  int result                                           = 1;
2625
2626
243
  if( file_entry == NULL )
2627
0
  {
2628
0
    libcerror_error_set(
2629
0
     error,
2630
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2631
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2632
0
     "%s: invalid file entry.",
2633
0
     function );
2634
2635
0
    return( -1 );
2636
0
  }
2637
243
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2638
2639
243
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2640
243
  if( libcthreads_read_write_lock_grab_for_write(
2641
243
       internal_file_entry->read_write_lock,
2642
243
       error ) != 1 )
2643
0
  {
2644
0
    libcerror_error_set(
2645
0
     error,
2646
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2647
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2648
0
     "%s: unable to grab read/write lock for writing.",
2649
0
     function );
2650
2651
0
    return( -1 );
2652
0
  }
2653
243
#endif
2654
243
  if( internal_file_entry->extended_attributes_array == NULL )
2655
243
  {
2656
243
    if( libfsapfs_internal_file_entry_get_extended_attributes(
2657
243
         internal_file_entry,
2658
243
         error ) != 1 )
2659
108
    {
2660
108
      libcerror_error_set(
2661
108
       error,
2662
108
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2663
108
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2664
108
       "%s: unable to determine extended attributes.",
2665
108
       function );
2666
2667
108
      result = -1;
2668
108
    }
2669
243
  }
2670
243
  if( internal_file_entry->extended_attributes_array != NULL )
2671
135
  {
2672
135
    if( libcdata_array_get_number_of_entries(
2673
135
         internal_file_entry->extended_attributes_array,
2674
135
         number_of_extended_attributes,
2675
135
         error ) != 1 )
2676
0
    {
2677
0
      libcerror_error_set(
2678
0
       error,
2679
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2680
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2681
0
       "%s: unable to retrieve number of entries from extended attributes array.",
2682
0
       function );
2683
2684
0
      result = -1;
2685
0
    }
2686
135
  }
2687
243
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2688
243
  if( libcthreads_read_write_lock_release_for_write(
2689
243
       internal_file_entry->read_write_lock,
2690
243
       error ) != 1 )
2691
0
  {
2692
0
    libcerror_error_set(
2693
0
     error,
2694
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2695
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2696
0
     "%s: unable to release read/write lock for writing.",
2697
0
     function );
2698
2699
0
    return( -1 );
2700
0
  }
2701
243
#endif
2702
243
  return( result );
2703
243
}
2704
2705
/* Retrieves the extended attribute for the specific index
2706
 * Returns 1 if successful or -1 on error
2707
 */
2708
int libfsapfs_file_entry_get_extended_attribute_by_index(
2709
     libfsapfs_file_entry_t *file_entry,
2710
     int extended_attribute_index,
2711
     libfsapfs_extended_attribute_t **extended_attribute,
2712
     libcerror_error_t **error )
2713
64
{
2714
64
  libfsapfs_attribute_values_t *attribute_values       = NULL;
2715
64
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2716
64
  static char *function                                = "libfsapfs_file_entry_get_extended_attribute_by_index";
2717
64
  int result                                           = 1;
2718
2719
64
  if( file_entry == NULL )
2720
0
  {
2721
0
    libcerror_error_set(
2722
0
     error,
2723
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2724
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2725
0
     "%s: invalid file entry.",
2726
0
     function );
2727
2728
0
    return( -1 );
2729
0
  }
2730
64
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2731
2732
64
  if( extended_attribute == NULL )
2733
0
  {
2734
0
    libcerror_error_set(
2735
0
     error,
2736
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2737
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2738
0
     "%s: invalid extended attribute.",
2739
0
     function );
2740
2741
0
    return( -1 );
2742
0
  }
2743
64
  if( *extended_attribute != NULL )
2744
0
  {
2745
0
    libcerror_error_set(
2746
0
     error,
2747
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2748
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2749
0
     "%s: invalid extended attribute value already set.",
2750
0
     function );
2751
2752
0
    return( -1 );
2753
0
  }
2754
64
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2755
64
  if( libcthreads_read_write_lock_grab_for_write(
2756
64
       internal_file_entry->read_write_lock,
2757
64
       error ) != 1 )
2758
0
  {
2759
0
    libcerror_error_set(
2760
0
     error,
2761
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2762
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2763
0
     "%s: unable to grab read/write lock for writing.",
2764
0
     function );
2765
2766
0
    return( -1 );
2767
0
  }
2768
64
#endif
2769
64
  if( internal_file_entry->extended_attributes_array == NULL )
2770
0
  {
2771
0
    if( libfsapfs_internal_file_entry_get_extended_attributes(
2772
0
         internal_file_entry,
2773
0
         error ) != 1 )
2774
0
    {
2775
0
      libcerror_error_set(
2776
0
       error,
2777
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2778
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2779
0
       "%s: unable to determine extended attributes.",
2780
0
       function );
2781
2782
0
      result = -1;
2783
0
    }
2784
0
  }
2785
64
  if( internal_file_entry->extended_attributes_array != NULL )
2786
64
  {
2787
64
    if( libcdata_array_get_entry_by_index(
2788
64
         internal_file_entry->extended_attributes_array,
2789
64
         extended_attribute_index,
2790
64
         (intptr_t **) &attribute_values,
2791
64
         error ) != 1 )
2792
0
    {
2793
0
      libcerror_error_set(
2794
0
       error,
2795
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2796
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2797
0
       "%s: unable to retrieve attribute: %d values.",
2798
0
       function,
2799
0
       extended_attribute_index );
2800
2801
0
      result = -1;
2802
0
    }
2803
64
    else
2804
64
    {
2805
64
      if( libfsapfs_extended_attribute_initialize(
2806
64
           extended_attribute,
2807
64
           internal_file_entry->io_handle,
2808
64
           internal_file_entry->file_io_handle,
2809
64
           internal_file_entry->encryption_context,
2810
64
           internal_file_entry->file_system_btree,
2811
64
           attribute_values,
2812
64
           internal_file_entry->transaction_identifier,
2813
64
           error ) != 1 )
2814
0
      {
2815
0
        libcerror_error_set(
2816
0
         error,
2817
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2818
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2819
0
         "%s: unable to create extended attribute.",
2820
0
         function );
2821
2822
0
        result = -1;
2823
0
      }
2824
64
    }
2825
64
  }
2826
64
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2827
64
  if( libcthreads_read_write_lock_release_for_write(
2828
64
       internal_file_entry->read_write_lock,
2829
64
       error ) != 1 )
2830
0
  {
2831
0
    libcerror_error_set(
2832
0
     error,
2833
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2834
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2835
0
     "%s: unable to release read/write lock for writing.",
2836
0
     function );
2837
2838
0
    return( -1 );
2839
0
  }
2840
64
#endif
2841
64
  return( result );
2842
64
}
2843
2844
/* Retrieves the attribute values for an UTF-8 encoded name
2845
 * Returns 1 if successful, 0 if no such file entry or -1 on error
2846
 */
2847
int libfsapfs_internal_file_entry_get_attribute_values_by_utf8_name(
2848
     libfsapfs_internal_file_entry_t *internal_file_entry,
2849
     const uint8_t *utf8_string,
2850
     size_t utf8_string_length,
2851
     libfsapfs_attribute_values_t **attribute_values,
2852
     libcerror_error_t **error )
2853
0
{
2854
0
  libfsapfs_attribute_values_t *safe_attribute_values = NULL;
2855
0
  static char *function                               = "libfsapfs_internal_file_entry_get_attribute_values_by_utf8_name";
2856
0
  int attribute_index                                 = 0;
2857
0
  int number_of_attributes                            = 0;
2858
0
  int result                                          = 0;
2859
2860
0
  if( internal_file_entry == NULL )
2861
0
  {
2862
0
    libcerror_error_set(
2863
0
     error,
2864
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2865
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2866
0
     "%s: invalid file entry.",
2867
0
     function );
2868
2869
0
    return( -1 );
2870
0
  }
2871
0
  if( internal_file_entry->extended_attributes_array == NULL )
2872
0
  {
2873
0
    if( libfsapfs_internal_file_entry_get_extended_attributes(
2874
0
         internal_file_entry,
2875
0
         error ) != 1 )
2876
0
    {
2877
0
      libcerror_error_set(
2878
0
       error,
2879
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2880
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2881
0
       "%s: unable to determine extended attributes.",
2882
0
       function );
2883
2884
0
      return( -1 );
2885
0
    }
2886
0
  }
2887
0
  if( libcdata_array_get_number_of_entries(
2888
0
       internal_file_entry->extended_attributes_array,
2889
0
       &number_of_attributes,
2890
0
       error ) != 1 )
2891
0
  {
2892
0
    libcerror_error_set(
2893
0
     error,
2894
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2895
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2896
0
     "%s: unable to retrieve number of entries from extended attributes array.",
2897
0
     function );
2898
2899
0
    return( -1 );
2900
0
  }
2901
0
  for( attribute_index = 0;
2902
0
       attribute_index < number_of_attributes;
2903
0
       attribute_index++ )
2904
0
  {
2905
0
    if( libcdata_array_get_entry_by_index(
2906
0
         internal_file_entry->extended_attributes_array,
2907
0
         attribute_index,
2908
0
         (intptr_t **) &safe_attribute_values,
2909
0
         error ) != 1 )
2910
0
    {
2911
0
      libcerror_error_set(
2912
0
       error,
2913
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2914
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2915
0
       "%s: unable to retrieve attribute: %d values.",
2916
0
       function,
2917
0
       attribute_index );
2918
2919
0
      return( -1 );
2920
0
    }
2921
0
    result = libfsapfs_attribute_values_compare_name_with_utf8_string(
2922
0
              safe_attribute_values,
2923
0
              utf8_string,
2924
0
              utf8_string_length,
2925
0
              error );
2926
2927
0
    if( result == -1 )
2928
0
    {
2929
0
      libcerror_error_set(
2930
0
       error,
2931
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2932
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
2933
0
       "%s: unable to compare UTF-8 string with name of attribute: %d values.",
2934
0
       function,
2935
0
       attribute_index );
2936
2937
0
      return( -1 );
2938
0
    }
2939
0
    else if( result == LIBUNA_COMPARE_EQUAL )
2940
0
    {
2941
0
      *attribute_values = safe_attribute_values;
2942
2943
0
      return( 1 );
2944
0
    }
2945
0
  }
2946
0
  return( 0 );
2947
0
}
2948
2949
/* Retrieves the attribute values for an UTF-16 encoded name
2950
 * Returns 1 if successful, 0 if no such file entry or -1 on error
2951
 */
2952
int libfsapfs_internal_file_entry_get_attribute_values_by_utf16_name(
2953
     libfsapfs_internal_file_entry_t *internal_file_entry,
2954
     const uint16_t *utf16_string,
2955
     size_t utf16_string_length,
2956
     libfsapfs_attribute_values_t **attribute_values,
2957
     libcerror_error_t **error )
2958
0
{
2959
0
  libfsapfs_attribute_values_t *safe_attribute_values = NULL;
2960
0
  static char *function                               = "libfsapfs_internal_file_entry_get_attribute_values_by_utf16_name";
2961
0
  int attribute_index                                 = 0;
2962
0
  int number_of_attributes                            = 0;
2963
0
  int result                                          = 0;
2964
2965
0
  if( internal_file_entry == NULL )
2966
0
  {
2967
0
    libcerror_error_set(
2968
0
     error,
2969
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2970
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2971
0
     "%s: invalid file entry.",
2972
0
     function );
2973
2974
0
    return( -1 );
2975
0
  }
2976
0
  if( internal_file_entry->extended_attributes_array == NULL )
2977
0
  {
2978
0
    if( libfsapfs_internal_file_entry_get_extended_attributes(
2979
0
         internal_file_entry,
2980
0
         error ) != 1 )
2981
0
    {
2982
0
      libcerror_error_set(
2983
0
       error,
2984
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2985
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2986
0
       "%s: unable to determine extended attributes.",
2987
0
       function );
2988
2989
0
      return( -1 );
2990
0
    }
2991
0
  }
2992
0
  if( libcdata_array_get_number_of_entries(
2993
0
       internal_file_entry->extended_attributes_array,
2994
0
       &number_of_attributes,
2995
0
       error ) != 1 )
2996
0
  {
2997
0
    libcerror_error_set(
2998
0
     error,
2999
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3000
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3001
0
     "%s: unable to retrieve number of entries from extended attributes array.",
3002
0
     function );
3003
3004
0
    return( -1 );
3005
0
  }
3006
0
  for( attribute_index = 0;
3007
0
       attribute_index < number_of_attributes;
3008
0
       attribute_index++ )
3009
0
  {
3010
0
    if( libcdata_array_get_entry_by_index(
3011
0
         internal_file_entry->extended_attributes_array,
3012
0
         attribute_index,
3013
0
         (intptr_t **) &safe_attribute_values,
3014
0
         error ) != 1 )
3015
0
    {
3016
0
      libcerror_error_set(
3017
0
       error,
3018
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3019
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3020
0
       "%s: unable to retrieve attribute: %d values.",
3021
0
       function,
3022
0
       attribute_index );
3023
3024
0
      return( -1 );
3025
0
    }
3026
0
    result = libfsapfs_attribute_values_compare_name_with_utf16_string(
3027
0
              safe_attribute_values,
3028
0
              utf16_string,
3029
0
              utf16_string_length,
3030
0
              error );
3031
3032
0
    if( result == -1 )
3033
0
    {
3034
0
      libcerror_error_set(
3035
0
       error,
3036
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3037
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
3038
0
       "%s: unable to compare UTF-16 string with name of attribute: %d values.",
3039
0
       function,
3040
0
       attribute_index );
3041
3042
0
      return( -1 );
3043
0
    }
3044
0
    else if( result == LIBUNA_COMPARE_EQUAL )
3045
0
    {
3046
0
      *attribute_values = safe_attribute_values;
3047
3048
0
      return( 1 );
3049
0
    }
3050
0
  }
3051
0
  return( 0 );
3052
0
}
3053
3054
/* Determines if there is an extended attribute for an UTF-8 encoded name
3055
 * Returns 1 if available, 0 if not or -1 on error
3056
 */
3057
int libfsapfs_file_entry_has_extended_attribute_by_utf8_name(
3058
     libfsapfs_file_entry_t *file_entry,
3059
     const uint8_t *utf8_string,
3060
     size_t utf8_string_length,
3061
     libcerror_error_t **error )
3062
0
{
3063
0
  libfsapfs_attribute_values_t *attribute_values       = NULL;
3064
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3065
0
  static char *function                                = "libfsapfs_file_entry_has_extended_attribute_by_utf8_name";
3066
0
  int result                                           = 0;
3067
3068
0
  if( file_entry == NULL )
3069
0
  {
3070
0
    libcerror_error_set(
3071
0
     error,
3072
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3073
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3074
0
     "%s: invalid file entry.",
3075
0
     function );
3076
3077
0
    return( -1 );
3078
0
  }
3079
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3080
3081
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3082
0
  if( libcthreads_read_write_lock_grab_for_write(
3083
0
       internal_file_entry->read_write_lock,
3084
0
       error ) != 1 )
3085
0
  {
3086
0
    libcerror_error_set(
3087
0
     error,
3088
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3089
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3090
0
     "%s: unable to grab read/write lock for writing.",
3091
0
     function );
3092
3093
0
    return( -1 );
3094
0
  }
3095
0
#endif
3096
0
  result = libfsapfs_internal_file_entry_get_attribute_values_by_utf8_name(
3097
0
            internal_file_entry,
3098
0
            utf8_string,
3099
0
            utf8_string_length,
3100
0
            &attribute_values,
3101
0
            error );
3102
3103
0
  if( result == -1 )
3104
0
  {
3105
0
    libcerror_error_set(
3106
0
     error,
3107
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3108
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3109
0
     "%s: unable to retrieve attribute values for UTF-8 name.",
3110
0
     function );
3111
3112
0
    result = -1;
3113
0
  }
3114
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3115
0
  if( libcthreads_read_write_lock_release_for_write(
3116
0
       internal_file_entry->read_write_lock,
3117
0
       error ) != 1 )
3118
0
  {
3119
0
    libcerror_error_set(
3120
0
     error,
3121
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3122
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3123
0
     "%s: unable to release read/write lock for writing.",
3124
0
     function );
3125
3126
0
    return( -1 );
3127
0
  }
3128
0
#endif
3129
0
  return( result );
3130
0
}
3131
3132
/* Determines if there is an extended attribute for an UTF-8 encoded name
3133
 * Returns 1 if available, 0 if not or -1 on error
3134
 */
3135
int libfsapfs_file_entry_has_extended_attribute_by_utf16_name(
3136
     libfsapfs_file_entry_t *file_entry,
3137
     const uint16_t *utf16_string,
3138
     size_t utf16_string_length,
3139
     libcerror_error_t **error )
3140
0
{
3141
0
  libfsapfs_attribute_values_t *attribute_values       = NULL;
3142
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3143
0
  static char *function                                = "libfsapfs_file_entry_has_extended_attribute_by_utf16_name";
3144
0
  int result                                           = 0;
3145
3146
0
  if( file_entry == NULL )
3147
0
  {
3148
0
    libcerror_error_set(
3149
0
     error,
3150
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3151
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3152
0
     "%s: invalid file entry.",
3153
0
     function );
3154
3155
0
    return( -1 );
3156
0
  }
3157
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3158
3159
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3160
0
  if( libcthreads_read_write_lock_grab_for_write(
3161
0
       internal_file_entry->read_write_lock,
3162
0
       error ) != 1 )
3163
0
  {
3164
0
    libcerror_error_set(
3165
0
     error,
3166
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3167
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3168
0
     "%s: unable to grab read/write lock for writing.",
3169
0
     function );
3170
3171
0
    return( -1 );
3172
0
  }
3173
0
#endif
3174
0
  result = libfsapfs_internal_file_entry_get_attribute_values_by_utf16_name(
3175
0
            internal_file_entry,
3176
0
            utf16_string,
3177
0
            utf16_string_length,
3178
0
            &attribute_values,
3179
0
            error );
3180
3181
0
  if( result == -1 )
3182
0
  {
3183
0
    libcerror_error_set(
3184
0
     error,
3185
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3186
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3187
0
     "%s: unable to retrieve attribute values for UTF-16 name.",
3188
0
     function );
3189
3190
0
    result = -1;
3191
0
  }
3192
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3193
0
  if( libcthreads_read_write_lock_release_for_write(
3194
0
       internal_file_entry->read_write_lock,
3195
0
       error ) != 1 )
3196
0
  {
3197
0
    libcerror_error_set(
3198
0
     error,
3199
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3200
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3201
0
     "%s: unable to release read/write lock for writing.",
3202
0
     function );
3203
3204
0
    return( -1 );
3205
0
  }
3206
0
#endif
3207
0
  return( result );
3208
0
}
3209
3210
/* Retrieves the extended attribute for an UTF-8 encoded name
3211
 * Returns 1 if successful, 0 if no such file entry or -1 on error
3212
 */
3213
int libfsapfs_file_entry_get_extended_attribute_by_utf8_name(
3214
     libfsapfs_file_entry_t *file_entry,
3215
     const uint8_t *utf8_string,
3216
     size_t utf8_string_length,
3217
     libfsapfs_extended_attribute_t **extended_attribute,
3218
     libcerror_error_t **error )
3219
0
{
3220
0
  libfsapfs_attribute_values_t *attribute_values       = NULL;
3221
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3222
0
  static char *function                                = "libfsapfs_file_entry_get_extended_attribute_by_utf8_name";
3223
0
  int result                                           = 0;
3224
3225
0
  if( file_entry == NULL )
3226
0
  {
3227
0
    libcerror_error_set(
3228
0
     error,
3229
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3230
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3231
0
     "%s: invalid file entry.",
3232
0
     function );
3233
3234
0
    return( -1 );
3235
0
  }
3236
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3237
3238
0
  if( extended_attribute == NULL )
3239
0
  {
3240
0
    libcerror_error_set(
3241
0
     error,
3242
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3243
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3244
0
     "%s: invalid extended attribute.",
3245
0
     function );
3246
3247
0
    return( -1 );
3248
0
  }
3249
0
  if( *extended_attribute != NULL )
3250
0
  {
3251
0
    libcerror_error_set(
3252
0
     error,
3253
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3254
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3255
0
     "%s: invalid extended attribute value already set.",
3256
0
     function );
3257
3258
0
    return( -1 );
3259
0
  }
3260
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3261
0
  if( libcthreads_read_write_lock_grab_for_write(
3262
0
       internal_file_entry->read_write_lock,
3263
0
       error ) != 1 )
3264
0
  {
3265
0
    libcerror_error_set(
3266
0
     error,
3267
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3268
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3269
0
     "%s: unable to grab read/write lock for writing.",
3270
0
     function );
3271
3272
0
    return( -1 );
3273
0
  }
3274
0
#endif
3275
0
  result = libfsapfs_internal_file_entry_get_attribute_values_by_utf8_name(
3276
0
            internal_file_entry,
3277
0
            utf8_string,
3278
0
            utf8_string_length,
3279
0
            &attribute_values,
3280
0
            error );
3281
3282
0
  if( result == -1 )
3283
0
  {
3284
0
    libcerror_error_set(
3285
0
     error,
3286
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3287
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3288
0
     "%s: unable to retrieve extended attribute for UTF-8 name.",
3289
0
     function );
3290
3291
0
    result = -1;
3292
0
  }
3293
0
  else if( result != 0 )
3294
0
  {
3295
0
    if( libfsapfs_extended_attribute_initialize(
3296
0
         extended_attribute,
3297
0
         internal_file_entry->io_handle,
3298
0
         internal_file_entry->file_io_handle,
3299
0
         internal_file_entry->encryption_context,
3300
0
         internal_file_entry->file_system_btree,
3301
0
         attribute_values,
3302
0
         internal_file_entry->transaction_identifier,
3303
0
         error ) != 1 )
3304
0
    {
3305
0
      libcerror_error_set(
3306
0
       error,
3307
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3308
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3309
0
       "%s: unable to create extended attribute.",
3310
0
       function );
3311
3312
0
      result = -1;
3313
0
    }
3314
0
  }
3315
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3316
0
  if( libcthreads_read_write_lock_release_for_write(
3317
0
       internal_file_entry->read_write_lock,
3318
0
       error ) != 1 )
3319
0
  {
3320
0
    libcerror_error_set(
3321
0
     error,
3322
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3323
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3324
0
     "%s: unable to release read/write lock for writing.",
3325
0
     function );
3326
3327
0
    return( -1 );
3328
0
  }
3329
0
#endif
3330
0
  return( result );
3331
0
}
3332
3333
/* Retrieves the extended attribute for an UTF-16 encoded name
3334
 * Returns 1 if successful, 0 if no such file entry or -1 on error
3335
 */
3336
int libfsapfs_file_entry_get_extended_attribute_by_utf16_name(
3337
     libfsapfs_file_entry_t *file_entry,
3338
     const uint16_t *utf16_string,
3339
     size_t utf16_string_length,
3340
     libfsapfs_extended_attribute_t **extended_attribute,
3341
     libcerror_error_t **error )
3342
0
{
3343
0
  libfsapfs_attribute_values_t *attribute_values       = NULL;
3344
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3345
0
  static char *function                                = "libfsapfs_file_entry_get_extended_attribute_by_utf16_name";
3346
0
  int result                                           = 0;
3347
3348
0
  if( file_entry == NULL )
3349
0
  {
3350
0
    libcerror_error_set(
3351
0
     error,
3352
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3353
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3354
0
     "%s: invalid file entry.",
3355
0
     function );
3356
3357
0
    return( -1 );
3358
0
  }
3359
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3360
3361
0
  if( extended_attribute == NULL )
3362
0
  {
3363
0
    libcerror_error_set(
3364
0
     error,
3365
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3366
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3367
0
     "%s: invalid extended attribute.",
3368
0
     function );
3369
3370
0
    return( -1 );
3371
0
  }
3372
0
  if( *extended_attribute != NULL )
3373
0
  {
3374
0
    libcerror_error_set(
3375
0
     error,
3376
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3377
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3378
0
     "%s: invalid extended attribute value already set.",
3379
0
     function );
3380
3381
0
    return( -1 );
3382
0
  }
3383
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3384
0
  if( libcthreads_read_write_lock_grab_for_write(
3385
0
       internal_file_entry->read_write_lock,
3386
0
       error ) != 1 )
3387
0
  {
3388
0
    libcerror_error_set(
3389
0
     error,
3390
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3391
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3392
0
     "%s: unable to grab read/write lock for writing.",
3393
0
     function );
3394
3395
0
    return( -1 );
3396
0
  }
3397
0
#endif
3398
0
  result = libfsapfs_internal_file_entry_get_attribute_values_by_utf16_name(
3399
0
            internal_file_entry,
3400
0
            utf16_string,
3401
0
            utf16_string_length,
3402
0
            &attribute_values,
3403
0
            error );
3404
3405
0
  if( result == -1 )
3406
0
  {
3407
0
    libcerror_error_set(
3408
0
     error,
3409
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3410
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3411
0
     "%s: unable to retrieve extended attribute for UTF-16 name.",
3412
0
     function );
3413
3414
0
    result = -1;
3415
0
  }
3416
0
  else if( result != 0 )
3417
0
  {
3418
0
    if( libfsapfs_extended_attribute_initialize(
3419
0
         extended_attribute,
3420
0
         internal_file_entry->io_handle,
3421
0
         internal_file_entry->file_io_handle,
3422
0
         internal_file_entry->encryption_context,
3423
0
         internal_file_entry->file_system_btree,
3424
0
         attribute_values,
3425
0
         internal_file_entry->transaction_identifier,
3426
0
         error ) != 1 )
3427
0
    {
3428
0
      libcerror_error_set(
3429
0
       error,
3430
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3431
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3432
0
       "%s: unable to create extended attribute.",
3433
0
       function );
3434
3435
0
      result = -1;
3436
0
    }
3437
0
  }
3438
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3439
0
  if( libcthreads_read_write_lock_release_for_write(
3440
0
       internal_file_entry->read_write_lock,
3441
0
       error ) != 1 )
3442
0
  {
3443
0
    libcerror_error_set(
3444
0
     error,
3445
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3446
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3447
0
     "%s: unable to release read/write lock for writing.",
3448
0
     function );
3449
3450
0
    return( -1 );
3451
0
  }
3452
0
#endif
3453
0
  return( result );
3454
0
}
3455
3456
/* Determines the directory entries
3457
 * Returns 1 if successful or -1 on error
3458
 */
3459
int libfsapfs_internal_file_entry_get_directory_entries(
3460
     libfsapfs_internal_file_entry_t *internal_file_entry,
3461
     libcerror_error_t **error )
3462
829
{
3463
829
  static char *function           = "libfsapfs_internal_file_entry_get_directory_entries";
3464
829
  uint64_t file_system_identifier = 0;
3465
829
  int result                      = 0;
3466
3467
829
  if( internal_file_entry == NULL )
3468
0
  {
3469
0
    libcerror_error_set(
3470
0
     error,
3471
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3472
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3473
0
     "%s: invalid file entry.",
3474
0
     function );
3475
3476
0
    return( -1 );
3477
0
  }
3478
829
  if( internal_file_entry->directory_entries != NULL )
3479
0
  {
3480
0
    libcerror_error_set(
3481
0
     error,
3482
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3483
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3484
0
     "%s: invalid file entry - directory entries value already set.",
3485
0
     function );
3486
3487
0
    return( -1 );
3488
0
  }
3489
829
  if( libfsapfs_inode_get_identifier(
3490
829
       internal_file_entry->inode,
3491
829
       &file_system_identifier,
3492
829
       error ) != 1 )
3493
0
  {
3494
0
    libcerror_error_set(
3495
0
     error,
3496
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3497
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3498
0
     "%s: unable to retrieve identifier from inode.",
3499
0
     function );
3500
3501
0
    goto on_error;
3502
0
  }
3503
829
  if( libcdata_array_initialize(
3504
829
       &( internal_file_entry->directory_entries ),
3505
829
       0,
3506
829
       error ) != 1 )
3507
0
  {
3508
0
    libcerror_error_set(
3509
0
     error,
3510
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3511
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3512
0
     "%s: unable to create directory entries array.",
3513
0
     function );
3514
3515
0
    goto on_error;
3516
0
  }
3517
829
  result = libfsapfs_file_system_btree_get_directory_entries(
3518
829
      internal_file_entry->file_system_btree,
3519
829
      internal_file_entry->file_io_handle,
3520
829
      file_system_identifier,
3521
829
      internal_file_entry->transaction_identifier,
3522
829
      internal_file_entry->directory_entries,
3523
829
      error );
3524
3525
829
  if( result == -1 )
3526
87
  {
3527
87
    libcerror_error_set(
3528
87
     error,
3529
87
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3530
87
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3531
87
     "%s: unable to retrieve directory entries from file system B-tree.",
3532
87
     function );
3533
3534
87
    goto on_error;
3535
87
  }
3536
742
  return( 1 );
3537
3538
87
on_error:
3539
87
  if( internal_file_entry->directory_entries != NULL )
3540
87
  {
3541
87
    libcdata_array_free(
3542
87
     &( internal_file_entry->directory_entries ),
3543
87
     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_directory_record_free,
3544
87
     NULL );
3545
87
  }
3546
87
  return( -1 );
3547
829
}
3548
3549
/* Retrieves the number of sub file entries
3550
 * Returns 1 if successful or -1 on error
3551
 */
3552
int libfsapfs_file_entry_get_number_of_sub_file_entries(
3553
     libfsapfs_file_entry_t *file_entry,
3554
     int *number_of_sub_file_entries,
3555
     libcerror_error_t **error )
3556
829
{
3557
829
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3558
829
  static char *function                                = "libfsapfs_file_entry_get_number_of_sub_file_entries";
3559
829
  int result                                           = 1;
3560
3561
829
  if( file_entry == NULL )
3562
0
  {
3563
0
    libcerror_error_set(
3564
0
     error,
3565
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3566
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3567
0
     "%s: invalid file entry.",
3568
0
     function );
3569
3570
0
    return( -1 );
3571
0
  }
3572
829
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3573
3574
829
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3575
829
  if( libcthreads_read_write_lock_grab_for_write(
3576
829
       internal_file_entry->read_write_lock,
3577
829
       error ) != 1 )
3578
0
  {
3579
0
    libcerror_error_set(
3580
0
     error,
3581
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3582
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3583
0
     "%s: unable to grab read/write lock for writing.",
3584
0
     function );
3585
3586
0
    return( -1 );
3587
0
  }
3588
829
#endif
3589
829
  if( internal_file_entry->directory_entries == NULL )
3590
829
  {
3591
829
    if( libfsapfs_internal_file_entry_get_directory_entries(
3592
829
         internal_file_entry,
3593
829
         error ) != 1 )
3594
87
    {
3595
87
      libcerror_error_set(
3596
87
       error,
3597
87
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3598
87
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3599
87
       "%s: unable to determine directory entries.",
3600
87
       function );
3601
3602
87
      result = -1;
3603
87
    }
3604
829
  }
3605
829
  if( result != -1 )
3606
742
  {
3607
742
    if( libcdata_array_get_number_of_entries(
3608
742
         internal_file_entry->directory_entries,
3609
742
         number_of_sub_file_entries,
3610
742
         error ) != 1 )
3611
0
    {
3612
0
      libcerror_error_set(
3613
0
       error,
3614
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3615
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3616
0
       "%s: unable to retrieve number of entries from array.",
3617
0
       function );
3618
3619
0
      result = -1;
3620
0
    }
3621
742
  }
3622
829
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3623
829
  if( libcthreads_read_write_lock_release_for_write(
3624
829
       internal_file_entry->read_write_lock,
3625
829
       error ) != 1 )
3626
0
  {
3627
0
    libcerror_error_set(
3628
0
     error,
3629
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3630
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3631
0
     "%s: unable to release read/write lock for writing.",
3632
0
     function );
3633
3634
0
    return( -1 );
3635
0
  }
3636
829
#endif
3637
829
  return( result );
3638
829
}
3639
3640
/* Retrieves the sub file entry for the specific index
3641
 * Returns 1 if successful or -1 on error
3642
 */
3643
int libfsapfs_file_entry_get_sub_file_entry_by_index(
3644
     libfsapfs_file_entry_t *file_entry,
3645
     int sub_file_entry_index,
3646
     libfsapfs_file_entry_t **sub_file_entry,
3647
     libcerror_error_t **error )
3648
659
{
3649
659
  libfsapfs_directory_record_t *directory_record       = NULL;
3650
659
  libfsapfs_directory_record_t *directory_record_copy  = NULL;
3651
659
  libfsapfs_inode_t *inode                             = NULL;
3652
659
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3653
659
  static char *function                                = "libfsapfs_file_entry_get_sub_file_entry_by_index";
3654
659
  uint64_t file_system_identifier                      = 0;
3655
3656
659
  if( file_entry == NULL )
3657
0
  {
3658
0
    libcerror_error_set(
3659
0
     error,
3660
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3661
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3662
0
     "%s: invalid file entry.",
3663
0
     function );
3664
3665
0
    return( -1 );
3666
0
  }
3667
659
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3668
3669
659
  if( sub_file_entry == NULL )
3670
0
  {
3671
0
    libcerror_error_set(
3672
0
     error,
3673
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3674
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3675
0
     "%s: invalid sub file entry.",
3676
0
     function );
3677
3678
0
    return( -1 );
3679
0
  }
3680
659
  if( *sub_file_entry != NULL )
3681
0
  {
3682
0
    libcerror_error_set(
3683
0
     error,
3684
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3685
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3686
0
     "%s: invalid sub file entry value already set.",
3687
0
     function );
3688
3689
0
    return( -1 );
3690
0
  }
3691
659
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3692
659
  if( libcthreads_read_write_lock_grab_for_write(
3693
659
       internal_file_entry->read_write_lock,
3694
659
       error ) != 1 )
3695
0
  {
3696
0
    libcerror_error_set(
3697
0
     error,
3698
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3699
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3700
0
     "%s: unable to grab read/write lock for writing.",
3701
0
     function );
3702
3703
0
    return( -1 );
3704
0
  }
3705
659
#endif
3706
659
  if( internal_file_entry->directory_entries == NULL )
3707
0
  {
3708
0
    if( libfsapfs_internal_file_entry_get_directory_entries(
3709
0
         internal_file_entry,
3710
0
         error ) != 1 )
3711
0
    {
3712
0
      libcerror_error_set(
3713
0
       error,
3714
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3715
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3716
0
       "%s: unable to determine directory entries.",
3717
0
       function );
3718
3719
0
      goto on_error;
3720
0
    }
3721
0
  }
3722
659
  if( libcdata_array_get_entry_by_index(
3723
659
       internal_file_entry->directory_entries,
3724
659
       sub_file_entry_index,
3725
659
       (intptr_t **) &directory_record,
3726
659
       error ) != 1 )
3727
0
  {
3728
0
    libcerror_error_set(
3729
0
     error,
3730
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3731
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3732
0
     "%s: unable to retrieve directory entry: %d.",
3733
0
     function,
3734
0
     sub_file_entry_index );
3735
3736
0
    goto on_error;
3737
0
  }
3738
659
  if( libfsapfs_directory_record_get_identifier(
3739
659
       directory_record,
3740
659
       &file_system_identifier,
3741
659
       error ) != 1 )
3742
0
  {
3743
0
    libcerror_error_set(
3744
0
     error,
3745
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3746
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3747
0
     "%s: unable to retrieve file system identifier from directory entry: %d.",
3748
0
     function,
3749
0
     sub_file_entry_index );
3750
3751
0
    goto on_error;
3752
0
  }
3753
659
  if( libfsapfs_file_system_btree_get_inode_by_identifier(
3754
659
       internal_file_entry->file_system_btree,
3755
659
       internal_file_entry->file_io_handle,
3756
659
       file_system_identifier,
3757
659
       internal_file_entry->transaction_identifier,
3758
659
       &inode,
3759
659
       error ) != 1 )
3760
43
  {
3761
43
    libcerror_error_set(
3762
43
     error,
3763
43
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3764
43
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3765
43
     "%s: unable to retrieve inode: %" PRIu64 " from file system B-tree.",
3766
43
     function,
3767
43
     file_system_identifier );
3768
3769
43
     goto on_error;
3770
43
  }
3771
616
  if( libfsapfs_directory_record_clone(
3772
616
       &directory_record_copy,
3773
616
       directory_record,
3774
616
       error ) != 1 )
3775
0
  {
3776
0
    libcerror_error_set(
3777
0
     error,
3778
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3779
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3780
0
     "%s: unable to create directory record copy.",
3781
0
     function );
3782
3783
0
    goto on_error;
3784
0
  }
3785
616
  if( libfsapfs_file_entry_initialize(
3786
616
       sub_file_entry,
3787
616
       internal_file_entry->io_handle,
3788
616
       internal_file_entry->file_io_handle,
3789
616
       internal_file_entry->encryption_context,
3790
616
       internal_file_entry->file_system_btree,
3791
616
       inode,
3792
616
       directory_record_copy,
3793
616
       internal_file_entry->transaction_identifier,
3794
616
       error ) != 1 )
3795
0
  {
3796
0
    libcerror_error_set(
3797
0
     error,
3798
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3799
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3800
0
     "%s: unable to create file entry.",
3801
0
     function );
3802
3803
0
    goto on_error;
3804
0
  }
3805
616
  inode                 = NULL;
3806
616
  directory_record_copy = NULL;
3807
3808
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3809
616
  if( libcthreads_read_write_lock_release_for_write(
3810
616
       internal_file_entry->read_write_lock,
3811
616
       error ) != 1 )
3812
0
  {
3813
0
    libcerror_error_set(
3814
0
     error,
3815
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3816
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3817
0
     "%s: unable to release read/write lock for writing.",
3818
0
     function );
3819
3820
0
    libfsapfs_file_entry_free(
3821
0
     sub_file_entry,
3822
0
     NULL );
3823
3824
0
    return( -1 );
3825
0
  }
3826
616
#endif
3827
616
  return( 1 );
3828
3829
43
on_error:
3830
43
  if( directory_record_copy != NULL )
3831
0
  {
3832
0
    libfsapfs_directory_record_free(
3833
0
     &directory_record_copy,
3834
0
     NULL );
3835
0
  }
3836
43
  if( inode != NULL )
3837
0
  {
3838
0
    libfsapfs_inode_free(
3839
0
     &inode,
3840
0
     NULL );
3841
0
  }
3842
43
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3843
43
  libcthreads_read_write_lock_release_for_write(
3844
43
   internal_file_entry->read_write_lock,
3845
43
   NULL );
3846
43
#endif
3847
43
  return( -1 );
3848
616
}
3849
3850
/* Retrieves the sub file entry for an UTF-8 encoded name
3851
 * Returns 1 if successful, 0 if no such file entry or -1 on error
3852
 */
3853
int libfsapfs_file_entry_get_sub_file_entry_by_utf8_name(
3854
     libfsapfs_file_entry_t *file_entry,
3855
     const uint8_t *utf8_string,
3856
     size_t utf8_string_length,
3857
     libfsapfs_file_entry_t **sub_file_entry,
3858
     libcerror_error_t **error )
3859
0
{
3860
0
  libfsapfs_directory_record_t *directory_record       = NULL;
3861
0
  libfsapfs_inode_t *inode                             = NULL;
3862
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3863
0
  static char *function                                = "libfsapfs_file_entry_get_sub_file_entry_by_utf8_name";
3864
0
  uint64_t file_system_identifier                      = 0;
3865
0
  int result                                           = 0;
3866
3867
0
  if( file_entry == NULL )
3868
0
  {
3869
0
    libcerror_error_set(
3870
0
     error,
3871
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3872
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3873
0
     "%s: invalid file entry.",
3874
0
     function );
3875
3876
0
    return( -1 );
3877
0
  }
3878
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3879
3880
0
  if( sub_file_entry == NULL )
3881
0
  {
3882
0
    libcerror_error_set(
3883
0
     error,
3884
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3885
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3886
0
     "%s: invalid sub file entry.",
3887
0
     function );
3888
3889
0
    return( -1 );
3890
0
  }
3891
0
  if( *sub_file_entry != NULL )
3892
0
  {
3893
0
    libcerror_error_set(
3894
0
     error,
3895
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3896
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3897
0
     "%s: invalid sub file entry value already set.",
3898
0
     function );
3899
3900
0
    return( -1 );
3901
0
  }
3902
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3903
0
  if( libcthreads_read_write_lock_grab_for_write(
3904
0
       internal_file_entry->read_write_lock,
3905
0
       error ) != 1 )
3906
0
  {
3907
0
    libcerror_error_set(
3908
0
     error,
3909
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3910
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3911
0
     "%s: unable to grab read/write lock for writing.",
3912
0
     function );
3913
3914
0
    return( -1 );
3915
0
  }
3916
0
#endif
3917
0
  if( libfsapfs_inode_get_identifier(
3918
0
       internal_file_entry->inode,
3919
0
       &file_system_identifier,
3920
0
       error ) != 1 )
3921
0
  {
3922
0
    libcerror_error_set(
3923
0
     error,
3924
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3925
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3926
0
     "%s: unable to retrieve identifier.",
3927
0
     function );
3928
3929
0
    goto on_error;
3930
0
  }
3931
0
  result = libfsapfs_file_system_btree_get_inode_by_utf8_path(
3932
0
            internal_file_entry->file_system_btree,
3933
0
            internal_file_entry->file_io_handle,
3934
0
            file_system_identifier,
3935
0
            utf8_string,
3936
0
            utf8_string_length,
3937
0
            internal_file_entry->transaction_identifier,
3938
0
            &inode,
3939
0
            &directory_record,
3940
0
            error );
3941
3942
0
  if( result == -1 )
3943
0
  {
3944
0
    libcerror_error_set(
3945
0
     error,
3946
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3947
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3948
0
     "%s: unable to retrieve inode from file system B-tree.",
3949
0
     function );
3950
3951
0
    goto on_error;
3952
0
  }
3953
0
  else if( result != 0 )
3954
0
  {
3955
0
    if( libfsapfs_file_entry_initialize(
3956
0
         sub_file_entry,
3957
0
         internal_file_entry->io_handle,
3958
0
         internal_file_entry->file_io_handle,
3959
0
         internal_file_entry->encryption_context,
3960
0
         internal_file_entry->file_system_btree,
3961
0
         inode,
3962
0
         directory_record,
3963
0
         internal_file_entry->transaction_identifier,
3964
0
         error ) != 1 )
3965
0
    {
3966
0
      libcerror_error_set(
3967
0
       error,
3968
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3969
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3970
0
       "%s: unable to create sub file entry.",
3971
0
       function );
3972
3973
0
      goto on_error;
3974
0
    }
3975
0
  }
3976
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3977
0
  if( libcthreads_read_write_lock_release_for_write(
3978
0
       internal_file_entry->read_write_lock,
3979
0
       error ) != 1 )
3980
0
  {
3981
0
    libcerror_error_set(
3982
0
     error,
3983
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3984
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3985
0
     "%s: unable to release read/write lock for writing.",
3986
0
     function );
3987
3988
0
    libfsapfs_file_entry_free(
3989
0
     sub_file_entry,
3990
0
     NULL );
3991
3992
0
    return( -1 );
3993
0
  }
3994
0
#endif
3995
0
  return( result );
3996
3997
0
on_error:
3998
0
  if( directory_record != NULL )
3999
0
  {
4000
0
    libfsapfs_directory_record_free(
4001
0
     &directory_record,
4002
0
     NULL );
4003
0
  }
4004
0
  if( inode != NULL )
4005
0
  {
4006
0
    libfsapfs_inode_free(
4007
0
     &inode,
4008
0
     NULL );
4009
0
  }
4010
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4011
0
  libcthreads_read_write_lock_release_for_write(
4012
0
   internal_file_entry->read_write_lock,
4013
0
   NULL );
4014
0
#endif
4015
0
  return( -1 );
4016
0
}
4017
4018
/* Retrieves the sub file entry for an UTF-16 encoded name
4019
 * Returns 1 if successful, 0 if no such file entry or -1 on error
4020
 */
4021
int libfsapfs_file_entry_get_sub_file_entry_by_utf16_name(
4022
     libfsapfs_file_entry_t *file_entry,
4023
     const uint16_t *utf16_string,
4024
     size_t utf16_string_length,
4025
     libfsapfs_file_entry_t **sub_file_entry,
4026
     libcerror_error_t **error )
4027
0
{
4028
0
  libfsapfs_directory_record_t *directory_record       = NULL;
4029
0
  libfsapfs_inode_t *inode                             = NULL;
4030
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4031
0
  static char *function                                = "libfsapfs_file_entry_get_sub_file_entry_by_utf16_name";
4032
0
  uint64_t file_system_identifier                      = 0;
4033
0
  int result                                           = 0;
4034
4035
0
  if( file_entry == NULL )
4036
0
  {
4037
0
    libcerror_error_set(
4038
0
     error,
4039
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4040
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4041
0
     "%s: invalid file entry.",
4042
0
     function );
4043
4044
0
    return( -1 );
4045
0
  }
4046
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4047
4048
0
  if( sub_file_entry == NULL )
4049
0
  {
4050
0
    libcerror_error_set(
4051
0
     error,
4052
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4053
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4054
0
     "%s: invalid sub file entry.",
4055
0
     function );
4056
4057
0
    return( -1 );
4058
0
  }
4059
0
  if( *sub_file_entry != NULL )
4060
0
  {
4061
0
    libcerror_error_set(
4062
0
     error,
4063
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4064
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4065
0
     "%s: invalid sub file entry value already set.",
4066
0
     function );
4067
4068
0
    return( -1 );
4069
0
  }
4070
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4071
0
  if( libcthreads_read_write_lock_grab_for_write(
4072
0
       internal_file_entry->read_write_lock,
4073
0
       error ) != 1 )
4074
0
  {
4075
0
    libcerror_error_set(
4076
0
     error,
4077
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4078
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4079
0
     "%s: unable to grab read/write lock for writing.",
4080
0
     function );
4081
4082
0
    return( -1 );
4083
0
  }
4084
0
#endif
4085
0
  if( libfsapfs_inode_get_identifier(
4086
0
       internal_file_entry->inode,
4087
0
       &file_system_identifier,
4088
0
       error ) != 1 )
4089
0
  {
4090
0
    libcerror_error_set(
4091
0
     error,
4092
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4093
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4094
0
     "%s: unable to retrieve identifier.",
4095
0
     function );
4096
4097
0
    goto on_error;
4098
0
  }
4099
0
  result = libfsapfs_file_system_btree_get_inode_by_utf16_path(
4100
0
            internal_file_entry->file_system_btree,
4101
0
            internal_file_entry->file_io_handle,
4102
0
            file_system_identifier,
4103
0
            utf16_string,
4104
0
            utf16_string_length,
4105
0
            internal_file_entry->transaction_identifier,
4106
0
            &inode,
4107
0
            &directory_record,
4108
0
            error );
4109
4110
0
  if( result == -1 )
4111
0
  {
4112
0
    libcerror_error_set(
4113
0
     error,
4114
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4115
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4116
0
     "%s: unable to retrieve inode from file system B-tree.",
4117
0
     function );
4118
4119
0
    goto on_error;
4120
0
  }
4121
0
  else if( result != 0 )
4122
0
  {
4123
0
    if( libfsapfs_file_entry_initialize(
4124
0
         sub_file_entry,
4125
0
         internal_file_entry->io_handle,
4126
0
         internal_file_entry->file_io_handle,
4127
0
         internal_file_entry->encryption_context,
4128
0
         internal_file_entry->file_system_btree,
4129
0
         inode,
4130
0
         directory_record,
4131
0
         internal_file_entry->transaction_identifier,
4132
0
         error ) != 1 )
4133
0
    {
4134
0
      libcerror_error_set(
4135
0
       error,
4136
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4137
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4138
0
       "%s: unable to create sub file entry.",
4139
0
       function );
4140
4141
0
      goto on_error;
4142
0
    }
4143
0
  }
4144
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4145
0
  if( libcthreads_read_write_lock_release_for_write(
4146
0
       internal_file_entry->read_write_lock,
4147
0
       error ) != 1 )
4148
0
  {
4149
0
    libcerror_error_set(
4150
0
     error,
4151
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4152
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4153
0
     "%s: unable to release read/write lock for writing.",
4154
0
     function );
4155
4156
0
    libfsapfs_file_entry_free(
4157
0
     sub_file_entry,
4158
0
     NULL );
4159
4160
0
    return( -1 );
4161
0
  }
4162
0
#endif
4163
0
  return( result );
4164
4165
0
on_error:
4166
0
  if( directory_record != NULL )
4167
0
  {
4168
0
    libfsapfs_directory_record_free(
4169
0
     &directory_record,
4170
0
     NULL );
4171
0
  }
4172
0
  if( inode != NULL )
4173
0
  {
4174
0
    libfsapfs_inode_free(
4175
0
     &inode,
4176
0
     NULL );
4177
0
  }
4178
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4179
0
  libcthreads_read_write_lock_release_for_write(
4180
0
   internal_file_entry->read_write_lock,
4181
0
   NULL );
4182
0
#endif
4183
0
  return( -1 );
4184
0
}
4185
4186
/* Determines the file extents
4187
 * Returns 1 if successful or -1 on error
4188
 */
4189
int libfsapfs_internal_file_entry_get_file_extents(
4190
     libfsapfs_internal_file_entry_t *internal_file_entry,
4191
     libcerror_error_t **error )
4192
666
{
4193
666
  static char *function           = "libfsapfs_internal_file_entry_get_file_extents";
4194
666
  uint64_t file_system_identifier = 0;
4195
666
  int result                      = 0;
4196
4197
666
  if( internal_file_entry == NULL )
4198
0
  {
4199
0
    libcerror_error_set(
4200
0
     error,
4201
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4202
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4203
0
     "%s: invalid file entry.",
4204
0
     function );
4205
4206
0
    return( -1 );
4207
0
  }
4208
666
  if( internal_file_entry->file_extents != NULL )
4209
0
  {
4210
0
    libcerror_error_set(
4211
0
     error,
4212
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4213
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4214
0
     "%s: invalid file entry - file extents value already set.",
4215
0
     function );
4216
4217
0
    return( -1 );
4218
0
  }
4219
666
  if( libfsapfs_inode_get_data_stream_identifier(
4220
666
       internal_file_entry->inode,
4221
666
       &file_system_identifier,
4222
666
       error ) != 1 )
4223
0
  {
4224
0
    libcerror_error_set(
4225
0
     error,
4226
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4227
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4228
0
     "%s: unable to retrieve data stream identifier from inode.",
4229
0
     function );
4230
4231
0
    goto on_error;
4232
0
  }
4233
666
  if( libcdata_array_initialize(
4234
666
       &( internal_file_entry->file_extents ),
4235
666
       0,
4236
666
       error ) != 1 )
4237
0
  {
4238
0
    libcerror_error_set(
4239
0
     error,
4240
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4241
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4242
0
     "%s: unable to create file extents array.",
4243
0
     function );
4244
4245
0
    goto on_error;
4246
0
  }
4247
666
  result = libfsapfs_file_system_btree_get_file_extents(
4248
666
      internal_file_entry->file_system_btree,
4249
666
      internal_file_entry->file_io_handle,
4250
666
      file_system_identifier,
4251
666
      internal_file_entry->transaction_identifier,
4252
666
      internal_file_entry->file_extents,
4253
666
      error );
4254
4255
666
  if( result == -1 )
4256
146
  {
4257
146
    libcerror_error_set(
4258
146
     error,
4259
146
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4260
146
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4261
146
     "%s: unable to retrieve file extents from file system B-tree.",
4262
146
     function );
4263
4264
146
    goto on_error;
4265
146
  }
4266
520
  return( 1 );
4267
4268
146
on_error:
4269
146
  if( internal_file_entry->file_extents != NULL )
4270
146
  {
4271
146
    libcdata_array_free(
4272
146
     &( internal_file_entry->file_extents ),
4273
146
     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
4274
146
     NULL );
4275
146
  }
4276
146
  return( -1 );
4277
666
}
4278
4279
/* Determines the data stream
4280
 * Returns 1 if successful or -1 on error
4281
 */
4282
int libfsapfs_internal_file_entry_get_data_stream(
4283
     libfsapfs_internal_file_entry_t *internal_file_entry,
4284
     libcerror_error_t **error )
4285
616
{
4286
616
  libfdata_stream_t *compressed_data_stream = NULL;
4287
616
  static char *function                     = "libfsapfs_internal_file_entry_get_data_stream";
4288
616
  uint64_t data_stream_size                 = 0;
4289
616
  uint64_t inode_flags                      = 0;
4290
616
  uint8_t is_sparse                         = 0;
4291
616
  int compression_method                    = 0;
4292
4293
616
  if( internal_file_entry == NULL )
4294
0
  {
4295
0
    libcerror_error_set(
4296
0
     error,
4297
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4298
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4299
0
     "%s: invalid file entry.",
4300
0
     function );
4301
4302
0
    return( -1 );
4303
0
  }
4304
616
  if( internal_file_entry->io_handle == NULL )
4305
0
  {
4306
0
    libcerror_error_set(
4307
0
     error,
4308
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4309
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4310
0
     "%s: invalid internal file entry - missing IO handle.",
4311
0
     function );
4312
4313
0
    return( -1 );
4314
0
  }
4315
616
  if( internal_file_entry->data_stream != NULL )
4316
0
  {
4317
0
    libcerror_error_set(
4318
0
     error,
4319
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4320
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4321
0
     "%s: invalid file entry - data stream value already set.",
4322
0
     function );
4323
4324
0
    return( -1 );
4325
0
  }
4326
616
  if( internal_file_entry->data_size == (size64_t) -1 )
4327
616
  {
4328
616
    if( libfsapfs_internal_file_entry_get_data_size(
4329
616
         internal_file_entry,
4330
616
         error ) != 1 )
4331
114
    {
4332
114
      libcerror_error_set(
4333
114
       error,
4334
114
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4335
114
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4336
114
       "%s: unable to determine data size.",
4337
114
       function );
4338
4339
114
      goto on_error;
4340
114
    }
4341
616
  }
4342
502
  if( internal_file_entry->compressed_data_header != NULL )
4343
0
  {
4344
0
    switch( internal_file_entry->compressed_data_header->compression_method )
4345
0
    {
4346
0
      case 3:
4347
0
      case 4:
4348
0
        compression_method = LIBFSAPFS_COMPRESSION_METHOD_DEFLATE;
4349
0
        break;
4350
4351
0
      case 5:
4352
0
        compression_method = LIBFSAPFS_COMPRESSION_METHOD_UNKNOWN5;
4353
0
        break;
4354
4355
0
      case 7:
4356
0
      case 8:
4357
0
        compression_method = LIBFSAPFS_COMPRESSION_METHOD_LZVN;
4358
0
        break;
4359
4360
0
      case 11:
4361
0
      case 12:
4362
0
        compression_method = LIBFSAPFS_COMPRESSION_METHOD_LZFSE;
4363
0
        break;
4364
4365
0
      default:
4366
0
        libcerror_error_set(
4367
0
         error,
4368
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4369
0
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4370
0
         "%s: unsupported compression method: %d.",
4371
0
         function,
4372
0
         internal_file_entry->compressed_data_header->compression_method );
4373
4374
0
        goto on_error;
4375
0
    }
4376
0
    if( ( internal_file_entry->compressed_data_header->compression_method == 4 )
4377
0
     || ( internal_file_entry->compressed_data_header->compression_method == 8 ) )
4378
0
    {
4379
0
      if( libfsapfs_attributes_get_data_stream(
4380
0
           internal_file_entry->resource_fork_attribute_values,
4381
0
           internal_file_entry->io_handle,
4382
0
           internal_file_entry->file_io_handle,
4383
0
           internal_file_entry->encryption_context,
4384
0
           internal_file_entry->file_system_btree,
4385
0
           internal_file_entry->transaction_identifier,
4386
0
           &compressed_data_stream,
4387
0
           error ) != 1 )
4388
0
      {
4389
0
        libcerror_error_set(
4390
0
         error,
4391
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4392
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4393
0
         "%s: unable to retrieve data stream from resource fork extended attribute.",
4394
0
         function );
4395
4396
0
        goto on_error;
4397
0
      }
4398
0
    }
4399
0
    else
4400
0
    {
4401
0
      if( libfsapfs_attributes_get_data_stream(
4402
0
           internal_file_entry->compressed_data_attribute_values,
4403
0
           internal_file_entry->io_handle,
4404
0
           internal_file_entry->file_io_handle,
4405
0
           internal_file_entry->encryption_context,
4406
0
           internal_file_entry->file_system_btree,
4407
0
           internal_file_entry->transaction_identifier,
4408
0
           &compressed_data_stream,
4409
0
           error ) != 1 )
4410
0
      {
4411
0
        libcerror_error_set(
4412
0
         error,
4413
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4414
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4415
0
         "%s: unable to retrieve data stream from compressed data extended attribute.",
4416
0
         function );
4417
4418
0
        goto on_error;
4419
0
      }
4420
0
    }
4421
0
    if( libfsapfs_data_stream_initialize_from_compressed_data_stream(
4422
0
         &( internal_file_entry->data_stream ),
4423
0
         compressed_data_stream,
4424
0
         internal_file_entry->data_size,
4425
0
         compression_method,
4426
0
         error ) != 1 )
4427
0
    {
4428
0
      libcerror_error_set(
4429
0
       error,
4430
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4431
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4432
0
       "%s: unable to create data stream from compressed data stream.",
4433
0
       function );
4434
4435
0
      goto on_error;
4436
0
    }
4437
0
  }
4438
502
  else
4439
502
  {
4440
502
    if( internal_file_entry->file_extents == NULL )
4441
502
    {
4442
502
      if( libfsapfs_internal_file_entry_get_file_extents(
4443
502
           internal_file_entry,
4444
502
           error ) != 1 )
4445
50
      {
4446
50
        libcerror_error_set(
4447
50
         error,
4448
50
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4449
50
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4450
50
         "%s: unable to determine file extents.",
4451
50
         function );
4452
4453
50
        goto on_error;
4454
50
      }
4455
502
    }
4456
452
    if( libfsapfs_inode_get_flags(
4457
452
         internal_file_entry->inode,
4458
452
         &inode_flags,
4459
452
         error ) != 1 )
4460
0
    {
4461
0
      libcerror_error_set(
4462
0
       error,
4463
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4464
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4465
0
       "%s: unable to retrieve flags from inode.",
4466
0
       function );
4467
4468
0
      goto on_error;
4469
0
    }
4470
452
    if( libfsapfs_inode_get_data_stream_size(
4471
452
         internal_file_entry->inode,
4472
452
         &data_stream_size,
4473
452
         error ) != 1 )
4474
0
    {
4475
0
      libcerror_error_set(
4476
0
       error,
4477
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4478
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4479
0
       "%s: unable to retrieve data stream size from inode.",
4480
0
       function );
4481
4482
0
      goto on_error;
4483
0
    }
4484
452
    is_sparse = (uint8_t) ( ( inode_flags & 0x00000200 ) != 0 );
4485
4486
452
    if( libfsapfs_data_stream_initialize_from_file_extents(
4487
452
         &( internal_file_entry->data_stream ),
4488
452
         internal_file_entry->io_handle,
4489
452
         internal_file_entry->encryption_context,
4490
452
         internal_file_entry->file_extents,
4491
452
         (size64_t) data_stream_size,
4492
452
         is_sparse,
4493
452
         error ) != 1 )
4494
247
    {
4495
247
      libcerror_error_set(
4496
247
       error,
4497
247
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4498
247
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4499
247
       "%s: unable to create data stream from file extents.",
4500
247
       function );
4501
4502
247
      goto on_error;
4503
247
    }
4504
452
  }
4505
205
  return( 1 );
4506
4507
411
on_error:
4508
411
  if( internal_file_entry->data_stream != NULL )
4509
0
  {
4510
0
    libfdata_stream_free(
4511
0
     &( internal_file_entry->data_stream ),
4512
0
     NULL );
4513
0
  }
4514
411
  return( -1 );
4515
502
}
4516
4517
/* Reads data at the current offset into a buffer
4518
 * Returns the number of bytes read or -1 on error
4519
 */
4520
ssize_t libfsapfs_file_entry_read_buffer(
4521
         libfsapfs_file_entry_t *file_entry,
4522
         void *buffer,
4523
         size_t buffer_size,
4524
         libcerror_error_t **error )
4525
0
{
4526
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4527
0
  static char *function                                = "libfsapfs_file_entry_read_buffer";
4528
0
  ssize_t read_count                                   = 0;
4529
4530
0
  if( file_entry == NULL )
4531
0
  {
4532
0
    libcerror_error_set(
4533
0
     error,
4534
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4535
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4536
0
     "%s: invalid file entry.",
4537
0
     function );
4538
4539
0
    return( -1 );
4540
0
  }
4541
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4542
4543
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4544
0
  if( libcthreads_read_write_lock_grab_for_write(
4545
0
       internal_file_entry->read_write_lock,
4546
0
       error ) != 1 )
4547
0
  {
4548
0
    libcerror_error_set(
4549
0
     error,
4550
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4551
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4552
0
     "%s: unable to grab read/write lock for writing.",
4553
0
     function );
4554
4555
0
    return( -1 );
4556
0
  }
4557
0
#endif
4558
0
  if( internal_file_entry->data_stream == NULL )
4559
0
  {
4560
0
    if( libfsapfs_internal_file_entry_get_data_stream(
4561
0
         internal_file_entry,
4562
0
         error ) != 1 )
4563
0
    {
4564
0
      libcerror_error_set(
4565
0
       error,
4566
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4567
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4568
0
       "%s: unable to determine data stream.",
4569
0
       function );
4570
4571
0
      read_count = -1;
4572
0
    }
4573
0
  }
4574
0
  if( read_count != -1 )
4575
0
  {
4576
0
    read_count = libfdata_stream_read_buffer(
4577
0
                  internal_file_entry->data_stream,
4578
0
                  (intptr_t *) internal_file_entry->file_io_handle,
4579
0
                  (uint8_t *) buffer,
4580
0
                  buffer_size,
4581
0
                  0,
4582
0
                  error );
4583
4584
0
    if( read_count < 0 )
4585
0
    {
4586
0
      libcerror_error_set(
4587
0
       error,
4588
0
       LIBCERROR_ERROR_DOMAIN_IO,
4589
0
       LIBCERROR_IO_ERROR_READ_FAILED,
4590
0
       "%s: unable to read buffer from data stream.",
4591
0
       function );
4592
4593
0
      read_count = -1;
4594
0
    }
4595
0
  }
4596
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4597
0
  if( libcthreads_read_write_lock_release_for_write(
4598
0
       internal_file_entry->read_write_lock,
4599
0
       error ) != 1 )
4600
0
  {
4601
0
    libcerror_error_set(
4602
0
     error,
4603
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4604
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4605
0
     "%s: unable to release read/write lock for writing.",
4606
0
     function );
4607
4608
0
    return( -1 );
4609
0
  }
4610
0
#endif
4611
0
  return( read_count );
4612
0
}
4613
4614
/* Reads data at a specific offset
4615
 * Returns the number of bytes read or -1 on error
4616
 */
4617
ssize_t libfsapfs_file_entry_read_buffer_at_offset(
4618
         libfsapfs_file_entry_t *file_entry,
4619
         void *buffer,
4620
         size_t buffer_size,
4621
         off64_t offset,
4622
         libcerror_error_t **error )
4623
0
{
4624
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4625
0
  static char *function                                = "libfsapfs_file_entry_read_buffer_at_offset";
4626
0
  ssize_t read_count                                   = 0;
4627
4628
0
  if( file_entry == NULL )
4629
0
  {
4630
0
    libcerror_error_set(
4631
0
     error,
4632
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4633
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4634
0
     "%s: invalid file entry.",
4635
0
     function );
4636
4637
0
    return( -1 );
4638
0
  }
4639
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4640
4641
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4642
0
  if( libcthreads_read_write_lock_grab_for_write(
4643
0
       internal_file_entry->read_write_lock,
4644
0
       error ) != 1 )
4645
0
  {
4646
0
    libcerror_error_set(
4647
0
     error,
4648
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4649
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4650
0
     "%s: unable to grab read/write lock for writing.",
4651
0
     function );
4652
4653
0
    return( -1 );
4654
0
  }
4655
0
#endif
4656
0
  if( internal_file_entry->data_stream == NULL )
4657
0
  {
4658
0
    if( libfsapfs_internal_file_entry_get_data_stream(
4659
0
         internal_file_entry,
4660
0
         error ) != 1 )
4661
0
    {
4662
0
      libcerror_error_set(
4663
0
       error,
4664
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4665
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4666
0
       "%s: unable to determine data stream.",
4667
0
       function );
4668
4669
0
      read_count = -1;
4670
0
    }
4671
0
  }
4672
0
  if( read_count != -1 )
4673
0
  {
4674
0
    read_count = libfdata_stream_read_buffer_at_offset(
4675
0
                  internal_file_entry->data_stream,
4676
0
                  (intptr_t *) internal_file_entry->file_io_handle,
4677
0
                  (uint8_t *) buffer,
4678
0
                  buffer_size,
4679
0
                  offset,
4680
0
                  0,
4681
0
                  error );
4682
4683
0
    if( read_count < 0 )
4684
0
    {
4685
0
      libcerror_error_set(
4686
0
       error,
4687
0
       LIBCERROR_ERROR_DOMAIN_IO,
4688
0
       LIBCERROR_IO_ERROR_READ_FAILED,
4689
0
       "%s: unable to read buffer at offset from data stream.",
4690
0
       function );
4691
4692
0
      read_count = -1;
4693
0
    }
4694
0
  }
4695
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4696
0
  if( libcthreads_read_write_lock_release_for_write(
4697
0
       internal_file_entry->read_write_lock,
4698
0
       error ) != 1 )
4699
0
  {
4700
0
    libcerror_error_set(
4701
0
     error,
4702
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4703
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4704
0
     "%s: unable to release read/write lock for writing.",
4705
0
     function );
4706
4707
0
    return( -1 );
4708
0
  }
4709
0
#endif
4710
0
  return( read_count );
4711
0
}
4712
4713
/* Seeks a certain offset
4714
 * Returns the offset if seek is successful or -1 on error
4715
 */
4716
off64_t libfsapfs_file_entry_seek_offset(
4717
         libfsapfs_file_entry_t *file_entry,
4718
         off64_t offset,
4719
         int whence,
4720
         libcerror_error_t **error )
4721
0
{
4722
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4723
0
  static char *function                                = "libfsapfs_file_entry_seek_offset";
4724
0
  off64_t result_offset                                = 0;
4725
4726
0
  if( file_entry == NULL )
4727
0
  {
4728
0
    libcerror_error_set(
4729
0
     error,
4730
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4731
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4732
0
     "%s: invalid file entry.",
4733
0
     function );
4734
4735
0
    return( -1 );
4736
0
  }
4737
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4738
4739
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4740
0
  if( libcthreads_read_write_lock_grab_for_write(
4741
0
       internal_file_entry->read_write_lock,
4742
0
       error ) != 1 )
4743
0
  {
4744
0
    libcerror_error_set(
4745
0
     error,
4746
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4747
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4748
0
     "%s: unable to grab read/write lock for writing.",
4749
0
     function );
4750
4751
0
    return( -1 );
4752
0
  }
4753
0
#endif
4754
0
  if( internal_file_entry->data_stream == NULL )
4755
0
  {
4756
0
    if( libfsapfs_internal_file_entry_get_data_stream(
4757
0
         internal_file_entry,
4758
0
         error ) != 1 )
4759
0
    {
4760
0
      libcerror_error_set(
4761
0
       error,
4762
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4763
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4764
0
       "%s: unable to determine data stream.",
4765
0
       function );
4766
4767
0
      result_offset = -1;
4768
0
    }
4769
0
  }
4770
0
  if( result_offset != -1 )
4771
0
  {
4772
0
    result_offset = libfdata_stream_seek_offset(
4773
0
                     internal_file_entry->data_stream,
4774
0
                     offset,
4775
0
                     whence,
4776
0
                     error );
4777
4778
0
    if( result_offset < 0 )
4779
0
    {
4780
0
      libcerror_error_set(
4781
0
       error,
4782
0
       LIBCERROR_ERROR_DOMAIN_IO,
4783
0
       LIBCERROR_IO_ERROR_SEEK_FAILED,
4784
0
       "%s: unable to seek offset in data stream.",
4785
0
       function );
4786
4787
0
      result_offset = -1;
4788
0
    }
4789
0
  }
4790
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4791
0
  if( libcthreads_read_write_lock_release_for_write(
4792
0
       internal_file_entry->read_write_lock,
4793
0
       error ) != 1 )
4794
0
  {
4795
0
    libcerror_error_set(
4796
0
     error,
4797
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4798
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4799
0
     "%s: unable to release read/write lock for writing.",
4800
0
     function );
4801
4802
0
    return( -1 );
4803
0
  }
4804
0
#endif
4805
0
  return( result_offset );
4806
0
}
4807
4808
/* Retrieves the current offset
4809
 * Returns the offset if successful or -1 on error
4810
 */
4811
int libfsapfs_file_entry_get_offset(
4812
     libfsapfs_file_entry_t *file_entry,
4813
     off64_t *offset,
4814
     libcerror_error_t **error )
4815
616
{
4816
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4817
616
  static char *function                                = "libfsapfs_file_entry_get_offset";
4818
616
  int result                                           = 1;
4819
4820
616
  if( file_entry == NULL )
4821
0
  {
4822
0
    libcerror_error_set(
4823
0
     error,
4824
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4825
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4826
0
     "%s: invalid file entry.",
4827
0
     function );
4828
4829
0
    return( -1 );
4830
0
  }
4831
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4832
4833
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4834
616
  if( libcthreads_read_write_lock_grab_for_write(
4835
616
       internal_file_entry->read_write_lock,
4836
616
       error ) != 1 )
4837
0
  {
4838
0
    libcerror_error_set(
4839
0
     error,
4840
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4841
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4842
0
     "%s: unable to grab read/write lock for writing.",
4843
0
     function );
4844
4845
0
    return( -1 );
4846
0
  }
4847
616
#endif
4848
616
  if( internal_file_entry->data_stream == NULL )
4849
616
  {
4850
616
    if( libfsapfs_internal_file_entry_get_data_stream(
4851
616
         internal_file_entry,
4852
616
         error ) != 1 )
4853
411
    {
4854
411
      libcerror_error_set(
4855
411
       error,
4856
411
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4857
411
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4858
411
       "%s: unable to determine data stream.",
4859
411
       function );
4860
4861
411
      result = -1;
4862
411
    }
4863
616
  }
4864
616
  if( result != -1 )
4865
205
  {
4866
205
    if( libfdata_stream_get_offset(
4867
205
         internal_file_entry->data_stream,
4868
205
         offset,
4869
205
         error ) != 1 )
4870
0
    {
4871
0
      libcerror_error_set(
4872
0
       error,
4873
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4874
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4875
0
       "%s: unable to retrieve offset from data stream.",
4876
0
       function );
4877
4878
0
      result = -1;
4879
0
    }
4880
205
  }
4881
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4882
616
  if( libcthreads_read_write_lock_release_for_write(
4883
616
       internal_file_entry->read_write_lock,
4884
616
       error ) != 1 )
4885
0
  {
4886
0
    libcerror_error_set(
4887
0
     error,
4888
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4889
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4890
0
     "%s: unable to release read/write lock for writing.",
4891
0
     function );
4892
4893
0
    return( -1 );
4894
0
  }
4895
616
#endif
4896
616
  return( result );
4897
616
}
4898
4899
/* Determines the data size
4900
 * Returns 1 if successful or -1 on error
4901
 */
4902
int libfsapfs_internal_file_entry_get_data_size(
4903
     libfsapfs_internal_file_entry_t *internal_file_entry,
4904
     libcerror_error_t **error )
4905
737
{
4906
737
  uint8_t compressed_data_header_data[ 16 ];
4907
4908
737
  libfdata_stream_t *data_stream = NULL;
4909
737
  static char *function          = "libfsapfs_internal_file_entry_get_data_size";
4910
737
  size64_t data_size             = 0;
4911
737
  ssize_t read_count             = 0;
4912
737
  int result                     = 0;
4913
4914
737
  if( internal_file_entry == NULL )
4915
0
  {
4916
0
    libcerror_error_set(
4917
0
     error,
4918
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4919
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4920
0
     "%s: invalid file entry.",
4921
0
     function );
4922
4923
0
    return( -1 );
4924
0
  }
4925
737
  if( internal_file_entry->compressed_data_header != NULL )
4926
0
  {
4927
0
    libcerror_error_set(
4928
0
     error,
4929
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4930
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4931
0
     "%s: invalid file entry - compressed data header value already set.",
4932
0
     function );
4933
4934
0
    return( -1 );
4935
0
  }
4936
737
  if( internal_file_entry->data_size != (size64_t) -1 )
4937
0
  {
4938
0
    libcerror_error_set(
4939
0
     error,
4940
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4941
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4942
0
     "%s: invalid file entry - data size value already set.",
4943
0
     function );
4944
4945
0
    return( -1 );
4946
0
  }
4947
737
  if( internal_file_entry->extended_attributes_array == NULL )
4948
228
  {
4949
228
    if( libfsapfs_internal_file_entry_get_extended_attributes(
4950
228
         internal_file_entry,
4951
228
         error ) != 1 )
4952
228
    {
4953
228
      libcerror_error_set(
4954
228
       error,
4955
228
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4956
228
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4957
228
       "%s: unable to determine extended attributes.",
4958
228
       function );
4959
4960
228
      return( -1 );
4961
228
    }
4962
228
  }
4963
509
  if( internal_file_entry->compressed_data_attribute_values != NULL )
4964
0
  {
4965
0
    if( libfsapfs_attributes_get_data_stream(
4966
0
         internal_file_entry->compressed_data_attribute_values,
4967
0
         internal_file_entry->io_handle,
4968
0
         internal_file_entry->file_io_handle,
4969
0
         internal_file_entry->encryption_context,
4970
0
         internal_file_entry->file_system_btree,
4971
0
         internal_file_entry->transaction_identifier,
4972
0
         &data_stream,
4973
0
         error ) != 1 )
4974
0
    {
4975
0
      libcerror_error_set(
4976
0
       error,
4977
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4978
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4979
0
       "%s: unable to retrieve data stream for compressed data extended attribute.",
4980
0
       function );
4981
4982
0
      goto on_error;
4983
0
    }
4984
/* TODO move into libfsapfs_compressed_data_header_read_data_stream */
4985
0
    read_count = libfdata_stream_read_buffer_at_offset(
4986
0
                  data_stream,
4987
0
                  (intptr_t *) internal_file_entry->file_io_handle,
4988
0
                  compressed_data_header_data,
4989
0
                  16,
4990
0
                  0,
4991
0
                  0,
4992
0
                  error );
4993
         
4994
0
    if( read_count != (ssize_t) 16 )
4995
0
    {
4996
0
      libcerror_error_set(
4997
0
       error,
4998
0
       LIBCERROR_ERROR_DOMAIN_IO,
4999
0
       LIBCERROR_IO_ERROR_READ_FAILED,
5000
0
       "%s: unable to read compressed data header data.",
5001
0
       function );
5002
5003
0
      return( -1 );
5004
0
    }
5005
0
    if( libfdata_stream_free(
5006
0
         &data_stream,
5007
0
         error ) != 1 )
5008
0
    {
5009
0
      libcerror_error_set(
5010
0
       error,
5011
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5012
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
5013
0
       "%s: unable to free symbolic link data stream.",
5014
0
       function );
5015
5016
0
      goto on_error;
5017
0
    }
5018
0
    if( libfsapfs_compressed_data_header_initialize(
5019
0
         &( internal_file_entry->compressed_data_header ),
5020
0
         error ) != 1 )
5021
0
    {
5022
0
      libcerror_error_set(
5023
0
       error,
5024
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5025
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
5026
0
       "%s: unable to create compressed data header.",
5027
0
       function );
5028
5029
0
      goto on_error;
5030
0
    }
5031
0
    result = libfsapfs_compressed_data_header_read_data(
5032
0
              internal_file_entry->compressed_data_header,
5033
0
              compressed_data_header_data,
5034
0
              16,
5035
0
              error );
5036
5037
0
    if( result == -1 )
5038
0
    {
5039
0
      libcerror_error_set(
5040
0
       error,
5041
0
       LIBCERROR_ERROR_DOMAIN_IO,
5042
0
       LIBCERROR_IO_ERROR_READ_FAILED,
5043
0
       "%s: unable to read compressed data header.",
5044
0
       function );
5045
5046
0
      goto on_error;
5047
0
    }
5048
0
    else if( result != 0 )
5049
0
    {
5050
0
      data_size = internal_file_entry->compressed_data_header->uncompressed_data_size;
5051
0
    }
5052
0
    else
5053
0
    {
5054
0
      if( libfsapfs_compressed_data_header_free(
5055
0
           &( internal_file_entry->compressed_data_header ),
5056
0
           error ) != 1 )
5057
0
      {
5058
0
        libcerror_error_set(
5059
0
         error,
5060
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5061
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
5062
0
         "%s: unable to free compressed data header.",
5063
0
         function );
5064
5065
0
        goto on_error;
5066
0
      }
5067
0
    }
5068
0
  }
5069
509
  if( result == 0 )
5070
509
  {
5071
509
    if( libfsapfs_inode_get_data_stream_size(
5072
509
         internal_file_entry->inode,
5073
509
         &data_size,
5074
509
         error ) != 1 )
5075
0
    {
5076
0
      libcerror_error_set(
5077
0
       error,
5078
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5079
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5080
0
       "%s: unable to retrieve data stream size from inode.",
5081
0
       function );
5082
5083
0
      return( -1 );
5084
0
    }
5085
509
  }
5086
509
  internal_file_entry->data_size = data_size;
5087
5088
509
  return( 1 );
5089
5090
0
on_error:
5091
0
  if( data_stream != NULL )
5092
0
  {
5093
0
    libfdata_stream_free(
5094
0
     &data_stream,
5095
0
     NULL );
5096
0
  }
5097
0
  if( internal_file_entry->compressed_data_header != NULL )
5098
0
  {
5099
0
    libfsapfs_compressed_data_header_free(
5100
0
     &( internal_file_entry->compressed_data_header ),
5101
0
     NULL );
5102
0
  }
5103
0
  return( -1 );
5104
509
}
5105
5106
/* Retrieves the size of the data stream object
5107
 * Returns 1 if successful or -1 on error
5108
 */
5109
int libfsapfs_file_entry_get_size(
5110
     libfsapfs_file_entry_t *file_entry,
5111
     size64_t *size,
5112
     libcerror_error_t **error )
5113
616
{
5114
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
5115
616
  static char *function                                = "libfsapfs_file_entry_get_size";
5116
616
  int result                                           = 1;
5117
5118
616
  if( file_entry == NULL )
5119
0
  {
5120
0
    libcerror_error_set(
5121
0
     error,
5122
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5123
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5124
0
     "%s: invalid file entry.",
5125
0
     function );
5126
5127
0
    return( -1 );
5128
0
  }
5129
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
5130
5131
616
  if( size == NULL )
5132
0
  {
5133
0
    libcerror_error_set(
5134
0
     error,
5135
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5136
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5137
0
     "%s: invalid size.",
5138
0
     function );
5139
5140
0
    return( -1 );
5141
0
  }
5142
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
5143
616
  if( libcthreads_read_write_lock_grab_for_write(
5144
616
       internal_file_entry->read_write_lock,
5145
616
       error ) != 1 )
5146
0
  {
5147
0
    libcerror_error_set(
5148
0
     error,
5149
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5150
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5151
0
     "%s: unable to grab read/write lock for writing.",
5152
0
     function );
5153
5154
0
    return( -1 );
5155
0
  }
5156
616
#endif
5157
616
  if( internal_file_entry->data_size == (size64_t) -1 )
5158
121
  {
5159
121
    if( libfsapfs_internal_file_entry_get_data_size(
5160
121
         internal_file_entry,
5161
121
         error ) != 1 )
5162
114
    {
5163
114
      libcerror_error_set(
5164
114
       error,
5165
114
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5166
114
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5167
114
       "%s: unable to determine data size.",
5168
114
       function );
5169
5170
114
      result = -1;
5171
114
    }
5172
121
  }
5173
616
  if( result != -1 )
5174
502
  {
5175
502
    *size = internal_file_entry->data_size;
5176
502
  }
5177
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
5178
616
  if( libcthreads_read_write_lock_release_for_write(
5179
616
       internal_file_entry->read_write_lock,
5180
616
       error ) != 1 )
5181
0
  {
5182
0
    libcerror_error_set(
5183
0
     error,
5184
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5185
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5186
0
     "%s: unable to release read/write lock for writing.",
5187
0
     function );
5188
5189
0
    return( -1 );
5190
0
  }
5191
616
#endif
5192
616
  return( result );
5193
616
}
5194
5195
/* Retrieves the number of extents
5196
 * Returns 1 if successful or -1 on error
5197
 */
5198
int libfsapfs_file_entry_get_number_of_extents(
5199
     libfsapfs_file_entry_t *file_entry,
5200
     int *number_of_extents,
5201
     libcerror_error_t **error )
5202
616
{
5203
616
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
5204
616
  static char *function                                = "libfsapfs_file_entry_get_number_of_extents";
5205
616
  int result                                           = 1;
5206
5207
616
  if( file_entry == NULL )
5208
0
  {
5209
0
    libcerror_error_set(
5210
0
     error,
5211
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5212
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5213
0
     "%s: invalid file entry.",
5214
0
     function );
5215
5216
0
    return( -1 );
5217
0
  }
5218
616
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
5219
5220
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
5221
616
  if( libcthreads_read_write_lock_grab_for_write(
5222
616
       internal_file_entry->read_write_lock,
5223
616
       error ) != 1 )
5224
0
  {
5225
0
    libcerror_error_set(
5226
0
     error,
5227
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5228
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5229
0
     "%s: unable to grab read/write lock for writing.",
5230
0
     function );
5231
5232
0
    return( -1 );
5233
0
  }
5234
616
#endif
5235
616
  if( internal_file_entry->file_extents == NULL )
5236
164
  {
5237
164
    if( libfsapfs_internal_file_entry_get_file_extents(
5238
164
         internal_file_entry,
5239
164
         error ) != 1 )
5240
96
    {
5241
96
      libcerror_error_set(
5242
96
       error,
5243
96
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5244
96
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5245
96
       "%s: unable to determine file extents.",
5246
96
       function );
5247
5248
96
      result = -1;
5249
96
    }
5250
164
  }
5251
616
  if( result != -1 )
5252
520
  {
5253
520
    if( libcdata_array_get_number_of_entries(
5254
520
         internal_file_entry->file_extents,
5255
520
         number_of_extents,
5256
520
         error ) != 1 )
5257
0
    {
5258
0
      libcerror_error_set(
5259
0
       error,
5260
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5261
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5262
0
       "%s: unable to retrieve number of entries from array.",
5263
0
       function );
5264
5265
0
      result = -1;
5266
0
    }
5267
520
  }
5268
616
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
5269
616
  if( libcthreads_read_write_lock_release_for_write(
5270
616
       internal_file_entry->read_write_lock,
5271
616
       error ) != 1 )
5272
0
  {
5273
0
    libcerror_error_set(
5274
0
     error,
5275
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5276
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5277
0
     "%s: unable to release read/write lock for writing.",
5278
0
     function );
5279
5280
0
    return( -1 );
5281
0
  }
5282
616
#endif
5283
616
  return( result );
5284
616
}
5285
5286
/* Retrieves a specific extent
5287
 * Returns 1 if successful or -1 on error
5288
 */
5289
int libfsapfs_file_entry_get_extent_by_index(
5290
     libfsapfs_file_entry_t *file_entry,
5291
     int extent_index,
5292
     off64_t *extent_offset,
5293
     size64_t *extent_size,
5294
     uint32_t *extent_flags,
5295
     libcerror_error_t **error )
5296
0
{
5297
0
  libfsapfs_file_extent_t *file_extent                 = NULL;
5298
0
  libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
5299
0
  static char *function                                = "libfsapfs_file_entry_get_extent_by_index";
5300
0
  int result                                           = 1;
5301
5302
0
  if( file_entry == NULL )
5303
0
  {
5304
0
    libcerror_error_set(
5305
0
     error,
5306
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5307
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5308
0
     "%s: invalid file entry.",
5309
0
     function );
5310
5311
0
    return( -1 );
5312
0
  }
5313
0
  internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
5314
5315
0
  if( internal_file_entry->io_handle == NULL )
5316
0
  {
5317
0
    libcerror_error_set(
5318
0
     error,
5319
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5320
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5321
0
     "%s: invalid internal file entry - missing IO handle.",
5322
0
     function );
5323
5324
0
    return( -1 );
5325
0
  }
5326
0
  if( extent_offset == NULL )
5327
0
  {
5328
0
    libcerror_error_set(
5329
0
     error,
5330
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5331
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5332
0
     "%s: invalid extent offset.",
5333
0
     function );
5334
5335
0
    return( -1 );
5336
0
  }
5337
0
  if( extent_size == NULL )
5338
0
  {
5339
0
    libcerror_error_set(
5340
0
     error,
5341
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5342
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5343
0
     "%s: invalid extent size.",
5344
0
     function );
5345
5346
0
    return( -1 );
5347
0
  }
5348
0
  if( extent_flags == NULL )
5349
0
  {
5350
0
    libcerror_error_set(
5351
0
     error,
5352
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5353
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5354
0
     "%s: invalid extent flags.",
5355
0
     function );
5356
5357
0
    return( -1 );
5358
0
  }
5359
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
5360
0
  if( libcthreads_read_write_lock_grab_for_write(
5361
0
       internal_file_entry->read_write_lock,
5362
0
       error ) != 1 )
5363
0
  {
5364
0
    libcerror_error_set(
5365
0
     error,
5366
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5367
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5368
0
     "%s: unable to grab read/write lock for writing.",
5369
0
     function );
5370
5371
0
    return( -1 );
5372
0
  }
5373
0
#endif
5374
0
  if( internal_file_entry->file_extents == NULL )
5375
0
  {
5376
0
    if( libfsapfs_internal_file_entry_get_file_extents(
5377
0
         internal_file_entry,
5378
0
         error ) != 1 )
5379
0
    {
5380
0
      libcerror_error_set(
5381
0
       error,
5382
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5383
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5384
0
       "%s: unable to determine file extents.",
5385
0
       function );
5386
5387
0
      result = -1;
5388
0
    }
5389
0
  }
5390
0
  if( result != -1 )
5391
0
  {
5392
0
    if( libcdata_array_get_entry_by_index(
5393
0
         internal_file_entry->file_extents,
5394
0
         extent_index,
5395
0
         (intptr_t **) &file_extent,
5396
0
         error ) != 1 )
5397
0
    {
5398
0
      libcerror_error_set(
5399
0
       error,
5400
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5401
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5402
0
       "%s: unable to retrieve file extent: %d.",
5403
0
       function,
5404
0
       extent_index );
5405
5406
0
      result = -1;
5407
0
    }
5408
0
    else if( file_extent == NULL )
5409
0
    {
5410
0
      libcerror_error_set(
5411
0
       error,
5412
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5413
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5414
0
       "%s: missing file extent: %d.",
5415
0
       function,
5416
0
       extent_index );
5417
5418
0
      result = -1;
5419
0
    }
5420
0
    else
5421
0
    {
5422
0
      *extent_offset = file_extent->physical_block_number * internal_file_entry->io_handle->block_size;
5423
0
      *extent_size   = file_extent->data_size;
5424
0
      *extent_flags  = 0;
5425
0
    }
5426
0
  }
5427
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
5428
0
  if( libcthreads_read_write_lock_release_for_write(
5429
0
       internal_file_entry->read_write_lock,
5430
0
       error ) != 1 )
5431
0
  {
5432
0
    libcerror_error_set(
5433
0
     error,
5434
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5435
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5436
0
     "%s: unable to release read/write lock for writing.",
5437
0
     function );
5438
5439
0
    return( -1 );
5440
0
  }
5441
0
#endif
5442
0
  return( result );
5443
0
}
5444