Coverage Report

Created: 2025-06-22 07:35

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