Coverage Report

Created: 2026-10-22 07:28

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