Coverage Report

Created: 2026-04-10 07:49

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