Coverage Report

Created: 2024-02-25 07:20

/src/libfsfat/libfsfat/libfsfat_file_entry.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * File entry functions
3
 *
4
 * Copyright (C) 2021-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <types.h>
25
26
#include "libfsfat_definitions.h"
27
#include "libfsfat_directory.h"
28
#include "libfsfat_directory_entry.h"
29
#include "libfsfat_extent.h"
30
#include "libfsfat_file_entry.h"
31
#include "libfsfat_file_system.h"
32
#include "libfsfat_io_handle.h"
33
#include "libfsfat_libbfio.h"
34
#include "libfsfat_libcdata.h"
35
#include "libfsfat_libcerror.h"
36
#include "libfsfat_libcthreads.h"
37
#include "libfsfat_libfdata.h"
38
#include "libfsfat_types.h"
39
40
/* Creates a file entry
41
 * Make sure the value file_entry is referencing, is set to NULL
42
 * Returns 1 if successful or -1 on error
43
 */
44
int libfsfat_file_entry_initialize(
45
     libfsfat_file_entry_t **file_entry,
46
     libfsfat_io_handle_t *io_handle,
47
     libbfio_handle_t *file_io_handle,
48
     libfsfat_file_system_t *file_system,
49
     uint64_t identifier,
50
     libfsfat_directory_entry_t *directory_entry,
51
     libfsfat_directory_t *directory,
52
     libcerror_error_t **error )
53
360
{
54
360
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
55
360
  static char *function                               = "libfsfat_file_entry_initialize";
56
360
  size64_t data_size                                  = 0;
57
360
  size64_t valid_data_size                            = 0;
58
360
  uint32_t cluster_number                             = 0;
59
360
  uint16_t file_attribute_flags                       = 0;
60
61
360
  if( file_entry == NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
66
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
67
0
     "%s: invalid file entry.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
360
  if( *file_entry != NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
77
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
78
0
     "%s: invalid file entry value already set.",
79
0
     function );
80
81
0
    return( -1 );
82
0
  }
83
360
  if( io_handle == NULL )
84
0
  {
85
0
    libcerror_error_set(
86
0
     error,
87
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
88
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
89
0
     "%s: invalid IO handle.",
90
0
     function );
91
92
0
    return( -1 );
93
0
  }
94
360
  if( directory_entry != NULL )
95
165
  {
96
165
    if( libfsfat_directory_entry_get_file_attribute_flags(
97
165
         directory_entry,
98
165
         &file_attribute_flags,
99
165
         error ) == -1 )
100
0
    {
101
0
      libcerror_error_set(
102
0
       error,
103
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
104
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
105
0
       "%s: unable to retrieve file attribute flags from directory entry.",
106
0
       function );
107
108
0
      goto on_error;
109
0
    }
110
165
    if( libfsfat_directory_entry_get_data_start_cluster(
111
165
         directory_entry,
112
165
         &cluster_number,
113
165
         error ) != 1 )
114
0
    {
115
0
      libcerror_error_set(
116
0
       error,
117
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
118
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
119
0
       "%s: unable to retrieve directory entry data start cluster.",
120
0
       function );
121
122
0
      goto on_error;
123
0
    }
124
165
    if( libfsfat_directory_entry_get_data_size(
125
165
         directory_entry,
126
165
         &data_size,
127
165
         error ) != 1 )
128
0
    {
129
0
      libcerror_error_set(
130
0
       error,
131
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
132
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
133
0
       "%s: unable to retrieve data size from directory entry.",
134
0
       function );
135
136
0
      goto on_error;
137
0
    }
138
165
    if( libfsfat_directory_entry_get_valid_data_size(
139
165
         directory_entry,
140
165
         &valid_data_size,
141
165
         error ) != 1 )
142
0
    {
143
0
      libcerror_error_set(
144
0
       error,
145
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
146
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
147
0
       "%s: unable to retrieve data size from directory entry.",
148
0
       function );
149
150
0
      goto on_error;
151
0
    }
152
165
    if( valid_data_size > 0 )
153
83
    {
154
83
      data_size = valid_data_size;
155
83
    }
156
165
  }
157
360
  internal_file_entry = memory_allocate_structure(
158
360
                         libfsfat_internal_file_entry_t );
159
160
360
  if( internal_file_entry == NULL )
161
0
  {
162
0
    libcerror_error_set(
163
0
     error,
164
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
165
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
166
0
     "%s: unable to create file entry.",
167
0
     function );
168
169
0
    goto on_error;
170
0
  }
171
360
  if( memory_set(
172
360
       internal_file_entry,
173
360
       0,
174
360
       sizeof( libfsfat_internal_file_entry_t ) ) == NULL )
175
0
  {
176
0
    libcerror_error_set(
177
0
     error,
178
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
179
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
180
0
     "%s: unable to clear file entry.",
181
0
     function );
182
183
0
    memory_free(
184
0
     internal_file_entry );
185
186
0
    return( -1 );
187
0
  }
188
360
  if( libcdata_array_initialize(
189
360
       &( internal_file_entry->data_extents_array ),
190
360
       0,
191
360
       error ) != 1 )
192
0
  {
193
0
    libcerror_error_set(
194
0
     error,
195
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
196
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
197
0
     "%s: unable to create data extents array.",
198
0
     function );
199
200
0
    goto on_error;
201
0
  }
202
360
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
203
360
  if( libcthreads_read_write_lock_initialize(
204
360
       &( internal_file_entry->read_write_lock ),
205
360
       error ) != 1 )
206
0
  {
207
0
    libcerror_error_set(
208
0
     error,
209
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
210
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
211
0
     "%s: unable to initialize read/write lock.",
212
0
     function );
213
214
0
    goto on_error;
215
0
  }
216
360
#endif
217
360
  internal_file_entry->io_handle            = io_handle;
218
360
  internal_file_entry->file_io_handle       = file_io_handle;
219
360
  internal_file_entry->file_system          = file_system;
220
360
  internal_file_entry->identifier           = identifier;
221
360
  internal_file_entry->directory_entry      = directory_entry;
222
360
  internal_file_entry->file_attribute_flags = file_attribute_flags;
223
360
  internal_file_entry->cluster_number       = cluster_number;
224
360
  internal_file_entry->data_size            = data_size;
225
360
  internal_file_entry->directory            = directory;
226
227
360
  *file_entry = (libfsfat_file_entry_t *) internal_file_entry;
228
229
360
  return( 1 );
230
231
0
on_error:
232
0
  if( internal_file_entry != NULL )
233
0
  {
234
0
    memory_free(
235
0
     internal_file_entry );
236
0
  }
237
0
  return( -1 );
238
360
}
239
240
/* Frees a file entry
241
 * Returns 1 if successful or -1 on error
242
 */
243
int libfsfat_file_entry_free(
244
     libfsfat_file_entry_t **file_entry,
245
     libcerror_error_t **error )
246
360
{
247
360
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
248
360
  static char *function                               = "libfsfat_file_entry_free";
249
360
  int result                                          = 1;
250
251
360
  if( file_entry == NULL )
252
0
  {
253
0
    libcerror_error_set(
254
0
     error,
255
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
256
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
257
0
     "%s: invalid file entry.",
258
0
     function );
259
260
0
    return( -1 );
261
0
  }
262
360
  if( *file_entry != NULL )
263
360
  {
264
360
    internal_file_entry = (libfsfat_internal_file_entry_t *) *file_entry;
265
360
    *file_entry         = NULL;
266
267
360
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
268
360
    if( libcthreads_read_write_lock_free(
269
360
         &( internal_file_entry->read_write_lock ),
270
360
         error ) != 1 )
271
0
    {
272
0
      libcerror_error_set(
273
0
       error,
274
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
275
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
276
0
       "%s: unable to free read/write lock.",
277
0
       function );
278
279
0
      result = -1;
280
0
    }
281
360
#endif
282
360
    if( internal_file_entry->directory_entry != NULL )
283
165
    {
284
165
      if( libfsfat_directory_entry_free(
285
165
           &( internal_file_entry->directory_entry ),
286
165
           error ) != 1 )
287
0
      {
288
0
        libcerror_error_set(
289
0
         error,
290
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
291
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
292
0
         "%s: unable to free directory entry.",
293
0
         function );
294
295
0
        result = -1;
296
0
      }
297
165
    }
298
360
    if( ( internal_file_entry->directory != NULL )
299
360
     && ( ( internal_file_entry->flags & LIBFSFAT_FILE_ENTRY_FLAG_MANAGE_DIRECTORY ) != 0 ) )
300
0
    {
301
0
      if( libfsfat_directory_free(
302
0
           &( internal_file_entry->directory ),
303
0
           error ) != 1 )
304
0
      {
305
0
        libcerror_error_set(
306
0
         error,
307
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
308
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
309
0
         "%s: unable to free directory.",
310
0
         function );
311
312
0
        result = -1;
313
0
      }
314
0
    }
315
360
    if( internal_file_entry->cluster_block_stream != NULL )
316
0
    {
317
0
      if( libfdata_stream_free(
318
0
           &( internal_file_entry->cluster_block_stream ),
319
0
           error ) != 1 )
320
0
      {
321
0
        libcerror_error_set(
322
0
         error,
323
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
324
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
325
0
         "%s: unable to free cluster block stream.",
326
0
         function );
327
328
0
        result = -1;
329
0
      }
330
0
    }
331
360
    if( libcdata_array_free(
332
360
         &( internal_file_entry->data_extents_array ),
333
360
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsfat_extent_free,
334
360
         error ) != 1 )
335
0
    {
336
0
      libcerror_error_set(
337
0
       error,
338
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
339
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
340
0
       "%s: unable to free data extents array.",
341
0
       function );
342
343
0
      result = -1;
344
0
    }
345
    /* The file_io_handle, io_handle and directory_entry references are freed elsewhere
346
     */
347
360
    memory_free(
348
360
     internal_file_entry );
349
360
  }
350
360
  return( result );
351
360
}
352
353
/* Determines the directory
354
 * Returns 1 if successful or -1 on error
355
 */
356
int libfsfat_internal_file_entry_get_directory(
357
     libfsfat_internal_file_entry_t *internal_file_entry,
358
     libcerror_error_t **error )
359
0
{
360
0
  static char *function   = "libfsfat_internal_file_entry_get_directory";
361
0
  uint32_t cluster_number = 0;
362
363
0
  if( internal_file_entry == NULL )
364
0
  {
365
0
    libcerror_error_set(
366
0
     error,
367
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
368
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
369
0
     "%s: invalid file entry.",
370
0
     function );
371
372
0
    return( -1 );
373
0
  }
374
0
  if( internal_file_entry->directory != NULL )
375
0
  {
376
0
    libcerror_error_set(
377
0
     error,
378
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
379
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
380
0
     "%s: invalid file entry - directory value already set.",
381
0
     function );
382
383
0
    return( -1 );
384
0
  }
385
0
  if( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_DIRECTORY ) != 0 )
386
0
  {
387
0
    if( libfsfat_directory_entry_get_data_start_cluster(
388
0
         internal_file_entry->directory_entry,
389
0
         &cluster_number,
390
0
         error ) != 1 )
391
0
    {
392
0
      libcerror_error_set(
393
0
       error,
394
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
395
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
396
0
       "%s: unable to retrieve directory entry data start cluster.",
397
0
       function );
398
399
0
      goto on_error;
400
0
    }
401
0
    if( libfsfat_file_system_read_directory(
402
0
         internal_file_entry->file_system,
403
0
         internal_file_entry->file_io_handle,
404
0
         cluster_number,
405
0
         &( internal_file_entry->directory ),
406
0
         error ) != 1 )
407
0
    {
408
0
      libcerror_error_set(
409
0
       error,
410
0
       LIBCERROR_ERROR_DOMAIN_IO,
411
0
       LIBCERROR_IO_ERROR_READ_FAILED,
412
0
       "%s: unable to read directory: %" PRIu32 ".",
413
0
       function,
414
0
       cluster_number );
415
416
0
      goto on_error;
417
0
    }
418
0
    internal_file_entry->flags |= LIBFSFAT_FILE_ENTRY_FLAG_MANAGE_DIRECTORY;
419
0
  }
420
0
  return( 1 );
421
422
0
on_error:
423
0
  if( internal_file_entry->directory != NULL )
424
0
  {
425
0
    libfsfat_directory_free(
426
0
     &( internal_file_entry->directory ),
427
0
     NULL );
428
0
  }
429
0
  return( -1 );
430
0
}
431
432
/* Retrieves the (virtual) identifier
433
 * The identifier is the offset of the short name directory entry
434
 * Returns 1 if successful or -1 on error
435
 */
436
int libfsfat_file_entry_get_identifier(
437
     libfsfat_file_entry_t *file_entry,
438
     uint64_t *identifier,
439
     libcerror_error_t **error )
440
0
{
441
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
442
0
  static char *function                               = "libfsfat_file_entry_get_identifier";
443
444
0
  if( file_entry == NULL )
445
0
  {
446
0
    libcerror_error_set(
447
0
     error,
448
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
449
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
450
0
     "%s: invalid file entry.",
451
0
     function );
452
453
0
    return( -1 );
454
0
  }
455
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
456
457
0
  if( identifier == NULL )
458
0
  {
459
0
    libcerror_error_set(
460
0
     error,
461
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
462
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
463
0
     "%s: invalid identifier.",
464
0
     function );
465
466
0
    return( -1 );
467
0
  }
468
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
469
0
  if( libcthreads_read_write_lock_grab_for_read(
470
0
       internal_file_entry->read_write_lock,
471
0
       error ) != 1 )
472
0
  {
473
0
    libcerror_error_set(
474
0
     error,
475
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
476
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
477
0
     "%s: unable to grab read/write lock for reading.",
478
0
     function );
479
480
0
    return( -1 );
481
0
  }
482
0
#endif
483
0
  *identifier = internal_file_entry->identifier;
484
485
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
486
0
  if( libcthreads_read_write_lock_release_for_read(
487
0
       internal_file_entry->read_write_lock,
488
0
       error ) != 1 )
489
0
  {
490
0
    libcerror_error_set(
491
0
     error,
492
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
493
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
494
0
     "%s: unable to release read/write lock for reading.",
495
0
     function );
496
497
0
    return( -1 );
498
0
  }
499
0
#endif
500
0
  return( 1 );
501
0
}
502
503
/* Retrieves the access date and time
504
 * The timestamp is an unsigned 64-bit integer containing the 10 milli seconds intervals since January 1, 1980
505
 * This value is retrieved from the short file name directory entry
506
 * Returns 1 if successful, 0 if not available or -1 on error
507
 */
508
int libfsfat_file_entry_get_access_time(
509
     libfsfat_file_entry_t *file_entry,
510
     uint64_t *fat_timestamp,
511
     libcerror_error_t **error )
512
0
{
513
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
514
0
  static char *function                               = "libfsfat_file_entry_get_access_time";
515
0
  int result                                          = 0;
516
517
0
  if( file_entry == NULL )
518
0
  {
519
0
    libcerror_error_set(
520
0
     error,
521
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
522
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
523
0
     "%s: invalid file entry.",
524
0
     function );
525
526
0
    return( -1 );
527
0
  }
528
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
529
530
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
531
0
  if( libcthreads_read_write_lock_grab_for_read(
532
0
       internal_file_entry->read_write_lock,
533
0
       error ) != 1 )
534
0
  {
535
0
    libcerror_error_set(
536
0
     error,
537
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
538
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
539
0
     "%s: unable to grab read/write lock for reading.",
540
0
     function );
541
542
0
    return( -1 );
543
0
  }
544
0
#endif
545
0
  if( internal_file_entry->directory_entry != NULL )
546
0
  {
547
0
    result = libfsfat_directory_entry_get_access_time(
548
0
              internal_file_entry->directory_entry,
549
0
              fat_timestamp,
550
0
              error );
551
552
0
    if( result == -1 )
553
0
    {
554
0
      libcerror_error_set(
555
0
       error,
556
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
557
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
558
0
       "%s: unable to retrieve access time from directory entry.",
559
0
       function );
560
561
0
      result = -1;
562
0
    }
563
0
  }
564
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
565
0
  if( libcthreads_read_write_lock_release_for_read(
566
0
       internal_file_entry->read_write_lock,
567
0
       error ) != 1 )
568
0
  {
569
0
    libcerror_error_set(
570
0
     error,
571
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
572
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
573
0
     "%s: unable to release read/write lock for reading.",
574
0
     function );
575
576
0
    return( -1 );
577
0
  }
578
0
#endif
579
0
  return( result );
580
0
}
581
582
/* Retrieves the creation date and time
583
 * The timestamp is an unsigned 64-bit integer containing the 10 milli seconds intervals since January 1, 1980
584
 * This value is retrieved from the short file name directory entry
585
 * Returns 1 if successful, 0 if not available or -1 on error
586
 */
587
int libfsfat_file_entry_get_creation_time(
588
     libfsfat_file_entry_t *file_entry,
589
     uint64_t *fat_date_time,
590
     libcerror_error_t **error )
591
0
{
592
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
593
0
  static char *function                               = "libfsfat_file_entry_get_creation_time";
594
0
  int result                                          = 0;
595
596
0
  if( file_entry == NULL )
597
0
  {
598
0
    libcerror_error_set(
599
0
     error,
600
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
601
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
602
0
     "%s: invalid file entry.",
603
0
     function );
604
605
0
    return( -1 );
606
0
  }
607
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
608
609
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
610
0
  if( libcthreads_read_write_lock_grab_for_read(
611
0
       internal_file_entry->read_write_lock,
612
0
       error ) != 1 )
613
0
  {
614
0
    libcerror_error_set(
615
0
     error,
616
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
617
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
618
0
     "%s: unable to grab read/write lock for reading.",
619
0
     function );
620
621
0
    return( -1 );
622
0
  }
623
0
#endif
624
0
  if( internal_file_entry->directory_entry != NULL )
625
0
  {
626
0
    result = libfsfat_directory_entry_get_creation_time(
627
0
              internal_file_entry->directory_entry,
628
0
              fat_date_time,
629
0
              error );
630
631
0
    if( result == -1 )
632
0
    {
633
0
      libcerror_error_set(
634
0
       error,
635
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
636
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
637
0
       "%s: unable to retrieve creation time from directory entry.",
638
0
       function );
639
640
0
      result = -1;
641
0
    }
642
0
  }
643
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
644
0
  if( libcthreads_read_write_lock_release_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 release read/write lock for reading.",
653
0
     function );
654
655
0
    return( -1 );
656
0
  }
657
0
#endif
658
0
  return( result );
659
0
}
660
661
/* Retrieves the modification date and time
662
 * The timestamp is an unsigned 64-bit integer containing the 10 milli seconds intervals since January 1, 1980
663
 * This value is retrieved from the short file name directory entry
664
 * Returns 1 if successful, 0 if not available or -1 on error
665
 */
666
int libfsfat_file_entry_get_modification_time(
667
     libfsfat_file_entry_t *file_entry,
668
     uint64_t *fat_date_time,
669
     libcerror_error_t **error )
670
0
{
671
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
672
0
  static char *function                               = "libfsfat_file_entry_get_modification_time";
673
0
  int result                                          = 0;
674
675
0
  if( file_entry == NULL )
676
0
  {
677
0
    libcerror_error_set(
678
0
     error,
679
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
680
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
681
0
     "%s: invalid file entry.",
682
0
     function );
683
684
0
    return( -1 );
685
0
  }
686
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
687
688
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
689
0
  if( libcthreads_read_write_lock_grab_for_read(
690
0
       internal_file_entry->read_write_lock,
691
0
       error ) != 1 )
692
0
  {
693
0
    libcerror_error_set(
694
0
     error,
695
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
696
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
697
0
     "%s: unable to grab read/write lock for reading.",
698
0
     function );
699
700
0
    return( -1 );
701
0
  }
702
0
#endif
703
0
  if( internal_file_entry->directory_entry != NULL )
704
0
  {
705
0
    result = libfsfat_directory_entry_get_modification_time(
706
0
              internal_file_entry->directory_entry,
707
0
              fat_date_time,
708
0
              error );
709
710
0
    if( result == -1 )
711
0
    {
712
0
      libcerror_error_set(
713
0
       error,
714
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
715
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
716
0
       "%s: unable to retrieve modification time from directory entry.",
717
0
       function );
718
719
0
      result = -1;
720
0
    }
721
0
  }
722
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
723
0
  if( libcthreads_read_write_lock_release_for_read(
724
0
       internal_file_entry->read_write_lock,
725
0
       error ) != 1 )
726
0
  {
727
0
    libcerror_error_set(
728
0
     error,
729
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
730
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
731
0
     "%s: unable to release read/write lock for reading.",
732
0
     function );
733
734
0
    return( -1 );
735
0
  }
736
0
#endif
737
0
  return( result );
738
0
}
739
740
/* Retrieves the file attribute flags
741
 * This value is retrieved from the short file name directory entry
742
 * Returns 1 if successful, 0 if not available or -1 on error
743
 */
744
int libfsfat_file_entry_get_file_attribute_flags(
745
     libfsfat_file_entry_t *file_entry,
746
     uint16_t *file_attribute_flags,
747
     libcerror_error_t **error )
748
0
{
749
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
750
0
  static char *function                               = "libfsfat_file_entry_get_file_attribute_flags";
751
0
  int result                                          = 0;
752
753
0
  if( file_entry == NULL )
754
0
  {
755
0
    libcerror_error_set(
756
0
     error,
757
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
758
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
759
0
     "%s: invalid file entry.",
760
0
     function );
761
762
0
    return( -1 );
763
0
  }
764
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
765
766
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
767
0
  if( libcthreads_read_write_lock_grab_for_read(
768
0
       internal_file_entry->read_write_lock,
769
0
       error ) != 1 )
770
0
  {
771
0
    libcerror_error_set(
772
0
     error,
773
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
774
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
775
0
     "%s: unable to grab read/write lock for reading.",
776
0
     function );
777
778
0
    return( -1 );
779
0
  }
780
0
#endif
781
0
  if( internal_file_entry->directory_entry != NULL )
782
0
  {
783
0
    result = libfsfat_directory_entry_get_file_attribute_flags(
784
0
              internal_file_entry->directory_entry,
785
0
              file_attribute_flags,
786
0
              error );
787
788
0
    if( result == -1 )
789
0
    {
790
0
      libcerror_error_set(
791
0
       error,
792
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
793
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
794
0
       "%s: unable to retrieve file attribute flags from directory entry.",
795
0
       function );
796
797
0
      result = -1;
798
0
    }
799
0
  }
800
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
801
0
  if( libcthreads_read_write_lock_release_for_read(
802
0
       internal_file_entry->read_write_lock,
803
0
       error ) != 1 )
804
0
  {
805
0
    libcerror_error_set(
806
0
     error,
807
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
808
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
809
0
     "%s: unable to release read/write lock for reading.",
810
0
     function );
811
812
0
    return( -1 );
813
0
  }
814
0
#endif
815
0
  return( result );
816
0
}
817
818
/* Retrieves the size of the UTF-8 encoded name
819
 * The returned size includes the end of string character
820
 * This value is retrieved from the directory entry
821
 * Returns 1 if successful, 0 if not available or -1 on error
822
 */
823
int libfsfat_file_entry_get_utf8_name_size(
824
     libfsfat_file_entry_t *file_entry,
825
     size_t *utf8_string_size,
826
     libcerror_error_t **error )
827
0
{
828
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
829
0
  static char *function                               = "libfsfat_file_entry_get_utf8_name_size";
830
0
  int result                                          = 0;
831
832
0
  if( file_entry == NULL )
833
0
  {
834
0
    libcerror_error_set(
835
0
     error,
836
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
837
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
838
0
     "%s: invalid file entry.",
839
0
     function );
840
841
0
    return( -1 );
842
0
  }
843
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
844
845
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
846
0
  if( libcthreads_read_write_lock_grab_for_read(
847
0
       internal_file_entry->read_write_lock,
848
0
       error ) != 1 )
849
0
  {
850
0
    libcerror_error_set(
851
0
     error,
852
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
853
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
854
0
     "%s: unable to grab read/write lock for reading.",
855
0
     function );
856
857
0
    return( -1 );
858
0
  }
859
0
#endif
860
0
  if( internal_file_entry->directory_entry != NULL )
861
0
  {
862
0
    result = libfsfat_directory_entry_get_utf8_name_size(
863
0
              internal_file_entry->directory_entry,
864
0
              utf8_string_size,
865
0
              error );
866
867
0
    if( result != 1 )
868
0
    {
869
0
      libcerror_error_set(
870
0
       error,
871
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
872
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
873
0
       "%s: unable to retrieve size of UTF-8 name from directory entry.",
874
0
       function );
875
876
0
      result = -1;
877
0
    }
878
0
  }
879
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
880
0
  if( libcthreads_read_write_lock_release_for_read(
881
0
       internal_file_entry->read_write_lock,
882
0
       error ) != 1 )
883
0
  {
884
0
    libcerror_error_set(
885
0
     error,
886
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
887
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
888
0
     "%s: unable to release read/write lock for reading.",
889
0
     function );
890
891
0
    return( -1 );
892
0
  }
893
0
#endif
894
0
  return( result );
895
0
}
896
897
/* Retrieves the UTF-8 encoded name
898
 * The size should include the end of string character
899
 * This value is retrieved from the directory entry
900
 * Returns 1 if successful, 0 if not available or -1 on error
901
 */
902
int libfsfat_file_entry_get_utf8_name(
903
     libfsfat_file_entry_t *file_entry,
904
     uint8_t *utf8_string,
905
     size_t utf8_string_size,
906
     libcerror_error_t **error )
907
0
{
908
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
909
0
  static char *function                               = "libfsfat_file_entry_get_utf8_name";
910
0
  int result                                          = 0;
911
912
0
  if( file_entry == NULL )
913
0
  {
914
0
    libcerror_error_set(
915
0
     error,
916
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
917
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
918
0
     "%s: invalid file entry.",
919
0
     function );
920
921
0
    return( -1 );
922
0
  }
923
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
924
925
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
926
0
  if( libcthreads_read_write_lock_grab_for_read(
927
0
       internal_file_entry->read_write_lock,
928
0
       error ) != 1 )
929
0
  {
930
0
    libcerror_error_set(
931
0
     error,
932
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
933
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
934
0
     "%s: unable to grab read/write lock for reading.",
935
0
     function );
936
937
0
    return( -1 );
938
0
  }
939
0
#endif
940
0
  if( internal_file_entry->directory_entry != NULL )
941
0
  {
942
0
    result = libfsfat_directory_entry_get_utf8_name(
943
0
              internal_file_entry->directory_entry,
944
0
              utf8_string,
945
0
              utf8_string_size,
946
0
              error );
947
948
0
    if( result != 1 )
949
0
    {
950
0
      libcerror_error_set(
951
0
       error,
952
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
953
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
954
0
       "%s: unable to retrieve UTF-8 name from directory entry.",
955
0
       function );
956
957
0
      result = -1;
958
0
    }
959
0
  }
960
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
961
0
  if( libcthreads_read_write_lock_release_for_read(
962
0
       internal_file_entry->read_write_lock,
963
0
       error ) != 1 )
964
0
  {
965
0
    libcerror_error_set(
966
0
     error,
967
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
968
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
969
0
     "%s: unable to release read/write lock for reading.",
970
0
     function );
971
972
0
    return( -1 );
973
0
  }
974
0
#endif
975
0
  return( result );
976
0
}
977
978
/* Retrieves the size of the UTF-16 encoded name
979
 * The returned size includes the end of string character
980
 * This value is retrieved from the directory entry
981
 * Returns 1 if successful, 0 if not available or -1 on error
982
 */
983
int libfsfat_file_entry_get_utf16_name_size(
984
     libfsfat_file_entry_t *file_entry,
985
     size_t *utf16_string_size,
986
     libcerror_error_t **error )
987
0
{
988
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
989
0
  static char *function                               = "libfsfat_file_entry_get_utf16_name_size";
990
0
  int result                                          = 0;
991
992
0
  if( file_entry == NULL )
993
0
  {
994
0
    libcerror_error_set(
995
0
     error,
996
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
997
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
998
0
     "%s: invalid file entry.",
999
0
     function );
1000
1001
0
    return( -1 );
1002
0
  }
1003
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
1004
1005
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1006
0
  if( libcthreads_read_write_lock_grab_for_read(
1007
0
       internal_file_entry->read_write_lock,
1008
0
       error ) != 1 )
1009
0
  {
1010
0
    libcerror_error_set(
1011
0
     error,
1012
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1013
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1014
0
     "%s: unable to grab read/write lock for reading.",
1015
0
     function );
1016
1017
0
    return( -1 );
1018
0
  }
1019
0
#endif
1020
0
  if( internal_file_entry->directory_entry != NULL )
1021
0
  {
1022
0
    result = libfsfat_directory_entry_get_utf16_name_size(
1023
0
              internal_file_entry->directory_entry,
1024
0
              utf16_string_size,
1025
0
              error );
1026
1027
0
    if( result != 1 )
1028
0
    {
1029
0
      libcerror_error_set(
1030
0
       error,
1031
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1032
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1033
0
       "%s: unable to retrieve size of UTF-16 name from directory entry.",
1034
0
       function );
1035
1036
0
      result = -1;
1037
0
    }
1038
0
  }
1039
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1040
0
  if( libcthreads_read_write_lock_release_for_read(
1041
0
       internal_file_entry->read_write_lock,
1042
0
       error ) != 1 )
1043
0
  {
1044
0
    libcerror_error_set(
1045
0
     error,
1046
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1047
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1048
0
     "%s: unable to release read/write lock for reading.",
1049
0
     function );
1050
1051
0
    return( -1 );
1052
0
  }
1053
0
#endif
1054
0
  return( result );
1055
0
}
1056
1057
/* Retrieves the UTF-16 encoded name
1058
 * The size should include the end of string character
1059
 * This value is retrieved from the directory entry
1060
 * Returns 1 if successful, 0 if not available or -1 on error
1061
 */
1062
int libfsfat_file_entry_get_utf16_name(
1063
     libfsfat_file_entry_t *file_entry,
1064
     uint16_t *utf16_string,
1065
     size_t utf16_string_size,
1066
     libcerror_error_t **error )
1067
0
{
1068
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
1069
0
  static char *function                               = "libfsfat_file_entry_get_utf16_name";
1070
0
  int result                                          = 0;
1071
1072
0
  if( file_entry == NULL )
1073
0
  {
1074
0
    libcerror_error_set(
1075
0
     error,
1076
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1077
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1078
0
     "%s: invalid file entry.",
1079
0
     function );
1080
1081
0
    return( -1 );
1082
0
  }
1083
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
1084
1085
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1086
0
  if( libcthreads_read_write_lock_grab_for_read(
1087
0
       internal_file_entry->read_write_lock,
1088
0
       error ) != 1 )
1089
0
  {
1090
0
    libcerror_error_set(
1091
0
     error,
1092
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1093
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1094
0
     "%s: unable to grab read/write lock for reading.",
1095
0
     function );
1096
1097
0
    return( -1 );
1098
0
  }
1099
0
#endif
1100
0
  if( internal_file_entry->directory_entry != NULL )
1101
0
  {
1102
0
    result = libfsfat_directory_entry_get_utf16_name(
1103
0
              internal_file_entry->directory_entry,
1104
0
              utf16_string,
1105
0
              utf16_string_size,
1106
0
              error );
1107
1108
0
    if( result != 1 )
1109
0
    {
1110
0
      libcerror_error_set(
1111
0
       error,
1112
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1113
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1114
0
       "%s: unable to retrieve UTF-16 name from directory entry.",
1115
0
       function );
1116
1117
0
      result = -1;
1118
0
    }
1119
0
  }
1120
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1121
0
  if( libcthreads_read_write_lock_release_for_read(
1122
0
       internal_file_entry->read_write_lock,
1123
0
       error ) != 1 )
1124
0
  {
1125
0
    libcerror_error_set(
1126
0
     error,
1127
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1128
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1129
0
     "%s: unable to release read/write lock for reading.",
1130
0
     function );
1131
1132
0
    return( -1 );
1133
0
  }
1134
0
#endif
1135
0
  return( result );
1136
0
}
1137
1138
/* Retrieves the number of sub file entries
1139
 * Returns 1 if successful or -1 on error
1140
 */
1141
int libfsfat_file_entry_get_number_of_sub_file_entries(
1142
     libfsfat_file_entry_t *file_entry,
1143
     int *number_of_sub_file_entries,
1144
     libcerror_error_t **error )
1145
195
{
1146
195
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
1147
195
  static char *function                               = "libfsfat_file_entry_get_number_of_sub_file_entries";
1148
195
  int result                                          = 1;
1149
195
  int safe_number_of_sub_file_entries                 = 0;
1150
1151
195
  if( file_entry == NULL )
1152
0
  {
1153
0
    libcerror_error_set(
1154
0
     error,
1155
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1156
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1157
0
     "%s: invalid file entry.",
1158
0
     function );
1159
1160
0
    return( -1 );
1161
0
  }
1162
195
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
1163
1164
195
  if( number_of_sub_file_entries == NULL )
1165
0
  {
1166
0
    libcerror_error_set(
1167
0
     error,
1168
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1169
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1170
0
     "%s: invalid number of sub file entries.",
1171
0
     function );
1172
1173
0
    return( -1 );
1174
0
  }
1175
195
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1176
195
  if( libcthreads_read_write_lock_grab_for_read(
1177
195
       internal_file_entry->read_write_lock,
1178
195
       error ) != 1 )
1179
0
  {
1180
0
    libcerror_error_set(
1181
0
     error,
1182
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1183
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1184
0
     "%s: unable to grab read/write lock for reading.",
1185
0
     function );
1186
1187
0
    return( -1 );
1188
0
  }
1189
195
#endif
1190
195
  if( internal_file_entry->directory == NULL )
1191
0
  {
1192
0
    if( libfsfat_internal_file_entry_get_directory(
1193
0
         internal_file_entry,
1194
0
         error ) != 1 )
1195
0
    {
1196
0
      libcerror_error_set(
1197
0
       error,
1198
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1199
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1200
0
       "%s: unable to determine directory.",
1201
0
       function );
1202
1203
0
      result = -1;
1204
0
    }
1205
0
  }
1206
195
  if( internal_file_entry->directory != NULL )
1207
195
  {
1208
195
    if( libfsfat_directory_get_number_of_file_entries(
1209
195
         internal_file_entry->directory,
1210
195
         &safe_number_of_sub_file_entries,
1211
195
         error ) != 1 )
1212
0
    {
1213
0
      libcerror_error_set(
1214
0
       error,
1215
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1216
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1217
0
       "%s: unable to retrieve number of file entries from directory.",
1218
0
       function );
1219
1220
0
      result = -1;
1221
0
    }
1222
195
  }
1223
195
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1224
195
  if( libcthreads_read_write_lock_release_for_read(
1225
195
       internal_file_entry->read_write_lock,
1226
195
       error ) != 1 )
1227
0
  {
1228
0
    libcerror_error_set(
1229
0
     error,
1230
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1231
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1232
0
     "%s: unable to release read/write lock for reading.",
1233
0
     function );
1234
1235
0
    return( -1 );
1236
0
  }
1237
195
#endif
1238
195
  *number_of_sub_file_entries = safe_number_of_sub_file_entries;
1239
1240
195
  return( result );
1241
195
}
1242
1243
/* Retrieves the sub file entry for the specific index
1244
 * Returns 1 if successful or -1 on error
1245
 */
1246
int libfsfat_internal_file_entry_get_sub_file_entry_by_index(
1247
     libfsfat_internal_file_entry_t *internal_file_entry,
1248
     int sub_file_entry_index,
1249
     libfsfat_file_entry_t **sub_file_entry,
1250
     libcerror_error_t **error )
1251
177
{
1252
177
  libfsfat_directory_entry_t *safe_directory_entry = NULL;
1253
177
  libfsfat_directory_entry_t *sub_directory_entry  = NULL;
1254
177
  static char *function                            = "libfsfat_internal_file_entry_get_sub_file_entry_by_index";
1255
177
  uint64_t identifier                              = 0;
1256
1257
177
  if( internal_file_entry == NULL )
1258
0
  {
1259
0
    libcerror_error_set(
1260
0
     error,
1261
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1262
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1263
0
     "%s: invalid file entry.",
1264
0
     function );
1265
1266
0
    return( -1 );
1267
0
  }
1268
177
  if( sub_file_entry == NULL )
1269
0
  {
1270
0
    libcerror_error_set(
1271
0
     error,
1272
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1273
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1274
0
     "%s: invalid sub file entry.",
1275
0
     function );
1276
1277
0
    return( -1 );
1278
0
  }
1279
177
  if( *sub_file_entry != NULL )
1280
0
  {
1281
0
    libcerror_error_set(
1282
0
     error,
1283
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1284
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1285
0
     "%s: invalid sub file entry value already set.",
1286
0
     function );
1287
1288
0
    return( -1 );
1289
0
  }
1290
177
  if( internal_file_entry->directory == NULL )
1291
0
  {
1292
0
    if( libfsfat_internal_file_entry_get_directory(
1293
0
         internal_file_entry,
1294
0
         error ) != 1 )
1295
0
    {
1296
0
      libcerror_error_set(
1297
0
       error,
1298
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1299
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1300
0
       "%s: unable to determine directory.",
1301
0
       function );
1302
1303
0
      goto on_error;
1304
0
    }
1305
0
  }
1306
177
  if( libfsfat_directory_get_file_entry_by_index(
1307
177
       internal_file_entry->directory,
1308
177
       sub_file_entry_index,
1309
177
       &sub_directory_entry,
1310
177
       error ) != 1 )
1311
0
  {
1312
0
    libcerror_error_set(
1313
0
     error,
1314
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1315
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1316
0
     "%s: unable to retrieve sub directory entry: %d.",
1317
0
     function,
1318
0
     sub_file_entry_index );
1319
1320
0
    goto on_error;
1321
0
  }
1322
177
  if( libfsfat_directory_entry_get_identifier(
1323
177
       sub_directory_entry,
1324
177
       &identifier,
1325
177
       error ) != 1 )
1326
0
  {
1327
0
    libcerror_error_set(
1328
0
     error,
1329
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1330
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1331
0
     "%s: unable to retrieve identifier from sub directory entry: %d.",
1332
0
     function,
1333
0
     sub_file_entry_index );
1334
1335
0
    goto on_error;
1336
0
  }
1337
177
  if( libfsfat_directory_entry_clone(
1338
177
       &safe_directory_entry,
1339
177
       sub_directory_entry,
1340
177
       error ) != 1 )
1341
12
  {
1342
12
    libcerror_error_set(
1343
12
     error,
1344
12
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1345
12
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1346
12
     "%s: unable to create sub directory entry: %d.",
1347
12
     function,
1348
12
     sub_file_entry_index );
1349
1350
12
    goto on_error;
1351
12
  }
1352
  /* libfsfat_file_entry_initialize takes over management of safe_directory_entry
1353
   */
1354
165
  if( libfsfat_file_entry_initialize(
1355
165
       sub_file_entry,
1356
165
       internal_file_entry->io_handle,
1357
165
       internal_file_entry->file_io_handle,
1358
165
       internal_file_entry->file_system,
1359
165
       identifier,
1360
165
       safe_directory_entry,
1361
165
       NULL,
1362
165
       error ) != 1 )
1363
0
  {
1364
0
    libcerror_error_set(
1365
0
     error,
1366
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1367
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1368
0
     "%s: unable to create file entry.",
1369
0
     function );
1370
1371
0
    goto on_error;
1372
0
  }
1373
165
  return( 1 );
1374
1375
12
on_error:
1376
12
  if( safe_directory_entry != NULL )
1377
0
  {
1378
0
    libfsfat_directory_entry_free(
1379
0
     &safe_directory_entry,
1380
0
     NULL );
1381
0
  }
1382
12
  return( -1 );
1383
165
}
1384
1385
/* Retrieves the sub file entry for the specific index
1386
 * Returns 1 if successful or -1 on error
1387
 */
1388
int libfsfat_file_entry_get_sub_file_entry_by_index(
1389
     libfsfat_file_entry_t *file_entry,
1390
     int sub_file_entry_index,
1391
     libfsfat_file_entry_t **sub_file_entry,
1392
     libcerror_error_t **error )
1393
177
{
1394
177
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
1395
177
  static char *function                               = "libfsfat_file_entry_get_sub_file_entry_by_index";
1396
177
  int result                                          = 1;
1397
1398
177
  if( file_entry == NULL )
1399
0
  {
1400
0
    libcerror_error_set(
1401
0
     error,
1402
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1403
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1404
0
     "%s: invalid file entry.",
1405
0
     function );
1406
1407
0
    return( -1 );
1408
0
  }
1409
177
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
1410
1411
177
  if( sub_file_entry == NULL )
1412
0
  {
1413
0
    libcerror_error_set(
1414
0
     error,
1415
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1416
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1417
0
     "%s: invalid sub file entry.",
1418
0
     function );
1419
1420
0
    return( -1 );
1421
0
  }
1422
177
  if( *sub_file_entry != NULL )
1423
0
  {
1424
0
    libcerror_error_set(
1425
0
     error,
1426
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1427
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1428
0
     "%s: invalid sub file entry value already set.",
1429
0
     function );
1430
1431
0
    return( -1 );
1432
0
  }
1433
177
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1434
177
  if( libcthreads_read_write_lock_grab_for_read(
1435
177
       internal_file_entry->read_write_lock,
1436
177
       error ) != 1 )
1437
0
  {
1438
0
    libcerror_error_set(
1439
0
     error,
1440
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1441
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1442
0
     "%s: unable to grab read/write lock for reading.",
1443
0
     function );
1444
1445
0
    return( -1 );
1446
0
  }
1447
177
#endif
1448
177
  if( libfsfat_internal_file_entry_get_sub_file_entry_by_index(
1449
177
       internal_file_entry,
1450
177
       sub_file_entry_index,
1451
177
       sub_file_entry,
1452
177
       error ) != 1 )
1453
12
  {
1454
12
    libcerror_error_set(
1455
12
     error,
1456
12
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1457
12
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1458
12
     "%s: unable to retrieve sub file entry: %d.",
1459
12
     function,
1460
12
     sub_file_entry_index );
1461
1462
12
    result = -1;
1463
12
  }
1464
177
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1465
177
  if( libcthreads_read_write_lock_release_for_read(
1466
177
       internal_file_entry->read_write_lock,
1467
177
       error ) != 1 )
1468
0
  {
1469
0
    libcerror_error_set(
1470
0
     error,
1471
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1472
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1473
0
     "%s: unable to release read/write lock for reading.",
1474
0
     function );
1475
1476
0
    return( -1 );
1477
0
  }
1478
177
#endif
1479
177
  return( result );
1480
177
}
1481
1482
/* Retrieves the sub file entry for an UTF-8 encoded name
1483
 * Returns 1 if successful, 0 if no such file entry or -1 on error
1484
 */
1485
int libfsfat_internal_file_entry_get_sub_file_entry_by_utf8_name(
1486
     libfsfat_internal_file_entry_t *internal_file_entry,
1487
     const uint8_t *utf8_string,
1488
     size_t utf8_string_length,
1489
     libfsfat_file_entry_t **sub_file_entry,
1490
     libcerror_error_t **error )
1491
0
{
1492
0
  libfsfat_directory_entry_t *safe_directory_entry = NULL;
1493
0
  libfsfat_directory_entry_t *sub_directory_entry  = NULL;
1494
0
  static char *function                            = "libfsfat_internal_file_entry_get_sub_file_entry_by_utf8_name";
1495
0
  uint64_t identifier                              = 0;
1496
0
  int result                                       = 0;
1497
1498
0
  if( internal_file_entry == NULL )
1499
0
  {
1500
0
    libcerror_error_set(
1501
0
     error,
1502
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1503
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1504
0
     "%s: invalid file entry.",
1505
0
     function );
1506
1507
0
    return( -1 );
1508
0
  }
1509
0
  if( sub_file_entry == NULL )
1510
0
  {
1511
0
    libcerror_error_set(
1512
0
     error,
1513
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1514
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1515
0
     "%s: invalid sub file entry.",
1516
0
     function );
1517
1518
0
    return( -1 );
1519
0
  }
1520
0
  if( *sub_file_entry != NULL )
1521
0
  {
1522
0
    libcerror_error_set(
1523
0
     error,
1524
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1525
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1526
0
     "%s: invalid sub file entry value already set.",
1527
0
     function );
1528
1529
0
    return( -1 );
1530
0
  }
1531
0
  if( internal_file_entry->directory == NULL )
1532
0
  {
1533
0
    if( libfsfat_internal_file_entry_get_directory(
1534
0
         internal_file_entry,
1535
0
         error ) != 1 )
1536
0
    {
1537
0
      libcerror_error_set(
1538
0
       error,
1539
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1540
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1541
0
       "%s: unable to determine directory.",
1542
0
       function );
1543
1544
0
      goto on_error;
1545
0
    }
1546
0
  }
1547
0
  result = libfsfat_directory_get_file_entry_by_utf8_name(
1548
0
            internal_file_entry->directory,
1549
0
            utf8_string,
1550
0
            utf8_string_length,
1551
0
            &sub_directory_entry,
1552
0
            error );
1553
1554
0
  if( result == -1 )
1555
0
  {
1556
0
    libcerror_error_set(
1557
0
     error,
1558
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1559
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1560
0
     "%s: unable to retrieve sub directory entry.",
1561
0
     function );
1562
1563
0
    goto on_error;
1564
0
  }
1565
0
  else if( result == 0 )
1566
0
  {
1567
0
    return( 0 );
1568
0
  }
1569
0
  if( libfsfat_directory_entry_get_identifier(
1570
0
       sub_directory_entry,
1571
0
       &identifier,
1572
0
       error ) != 1 )
1573
0
  {
1574
0
    libcerror_error_set(
1575
0
     error,
1576
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1577
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1578
0
     "%s: unable to retrieve identifier from sub directory entry.",
1579
0
     function );
1580
1581
0
    goto on_error;
1582
0
  }
1583
0
  if( libfsfat_directory_entry_clone(
1584
0
       &safe_directory_entry,
1585
0
       sub_directory_entry,
1586
0
       error ) != 1 )
1587
0
  {
1588
0
    libcerror_error_set(
1589
0
     error,
1590
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1591
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1592
0
     "%s: unable to create sub directory entry.",
1593
0
     function );
1594
1595
0
    goto on_error;
1596
0
  }
1597
  /* libfsfat_file_entry_initialize takes over management of safe_directory_entry
1598
   */
1599
0
  if( libfsfat_file_entry_initialize(
1600
0
       sub_file_entry,
1601
0
       internal_file_entry->io_handle,
1602
0
       internal_file_entry->file_io_handle,
1603
0
       internal_file_entry->file_system,
1604
0
       identifier,
1605
0
       safe_directory_entry,
1606
0
       NULL,
1607
0
       error ) != 1 )
1608
0
  {
1609
0
    libcerror_error_set(
1610
0
     error,
1611
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1612
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1613
0
     "%s: unable to create file entry.",
1614
0
     function );
1615
1616
0
    goto on_error;
1617
0
  }
1618
0
  return( 1 );
1619
1620
0
on_error:
1621
0
  if( safe_directory_entry != NULL )
1622
0
  {
1623
0
    libfsfat_directory_entry_free(
1624
0
     &safe_directory_entry,
1625
0
     NULL );
1626
0
  }
1627
0
  return( -1 );
1628
0
}
1629
1630
/* Retrieves the sub file entry for an UTF-8 encoded name
1631
 * Returns 1 if successful, 0 if no such file entry or -1 on error
1632
 */
1633
int libfsfat_file_entry_get_sub_file_entry_by_utf8_name(
1634
     libfsfat_file_entry_t *file_entry,
1635
     const uint8_t *utf8_string,
1636
     size_t utf8_string_length,
1637
     libfsfat_file_entry_t **sub_file_entry,
1638
     libcerror_error_t **error )
1639
0
{
1640
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
1641
0
  static char *function                               = "libfsfat_file_entry_get_sub_file_entry_by_utf8_name";
1642
0
  int result                                          = 1;
1643
1644
0
  if( file_entry == NULL )
1645
0
  {
1646
0
    libcerror_error_set(
1647
0
     error,
1648
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1649
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1650
0
     "%s: invalid file entry.",
1651
0
     function );
1652
1653
0
    return( -1 );
1654
0
  }
1655
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
1656
1657
0
  if( sub_file_entry == NULL )
1658
0
  {
1659
0
    libcerror_error_set(
1660
0
     error,
1661
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1662
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1663
0
     "%s: invalid sub file entry.",
1664
0
     function );
1665
1666
0
    return( -1 );
1667
0
  }
1668
0
  if( *sub_file_entry != NULL )
1669
0
  {
1670
0
    libcerror_error_set(
1671
0
     error,
1672
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1673
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1674
0
     "%s: invalid sub file entry value already set.",
1675
0
     function );
1676
1677
0
    return( -1 );
1678
0
  }
1679
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1680
0
  if( libcthreads_read_write_lock_grab_for_read(
1681
0
       internal_file_entry->read_write_lock,
1682
0
       error ) != 1 )
1683
0
  {
1684
0
    libcerror_error_set(
1685
0
     error,
1686
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1687
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1688
0
     "%s: unable to grab read/write lock for reading.",
1689
0
     function );
1690
1691
0
    return( -1 );
1692
0
  }
1693
0
#endif
1694
0
  if( libfsfat_internal_file_entry_get_sub_file_entry_by_utf8_name(
1695
0
       internal_file_entry,
1696
0
       utf8_string,
1697
0
       utf8_string_length,
1698
0
       sub_file_entry,
1699
0
       error ) != 1 )
1700
0
  {
1701
0
    libcerror_error_set(
1702
0
     error,
1703
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1704
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1705
0
     "%s: unable to retrieve sub file entry.",
1706
0
     function );
1707
1708
0
    result = -1;
1709
0
  }
1710
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1711
0
  if( libcthreads_read_write_lock_release_for_read(
1712
0
       internal_file_entry->read_write_lock,
1713
0
       error ) != 1 )
1714
0
  {
1715
0
    libcerror_error_set(
1716
0
     error,
1717
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1718
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1719
0
     "%s: unable to release read/write lock for reading.",
1720
0
     function );
1721
1722
0
    return( -1 );
1723
0
  }
1724
0
#endif
1725
0
  return( result );
1726
0
}
1727
1728
/* Retrieves the sub file entry for an UTF-16 encoded name
1729
 * Returns 1 if successful, 0 if no such file entry or -1 on error
1730
 */
1731
int libfsfat_internal_file_entry_get_sub_file_entry_by_utf16_name(
1732
     libfsfat_internal_file_entry_t *internal_file_entry,
1733
     const uint16_t *utf16_string,
1734
     size_t utf16_string_length,
1735
     libfsfat_file_entry_t **sub_file_entry,
1736
     libcerror_error_t **error )
1737
0
{
1738
0
  libfsfat_directory_entry_t *safe_directory_entry = NULL;
1739
0
  libfsfat_directory_entry_t *sub_directory_entry  = NULL;
1740
0
  static char *function                            = "libfsfat_internal_file_entry_get_sub_file_entry_by_utf16_name";
1741
0
  uint64_t identifier                              = 0;
1742
0
  int result                                       = 0;
1743
1744
0
  if( internal_file_entry == NULL )
1745
0
  {
1746
0
    libcerror_error_set(
1747
0
     error,
1748
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1749
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1750
0
     "%s: invalid file entry.",
1751
0
     function );
1752
1753
0
    return( -1 );
1754
0
  }
1755
0
  if( sub_file_entry == NULL )
1756
0
  {
1757
0
    libcerror_error_set(
1758
0
     error,
1759
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1760
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1761
0
     "%s: invalid sub file entry.",
1762
0
     function );
1763
1764
0
    return( -1 );
1765
0
  }
1766
0
  if( *sub_file_entry != NULL )
1767
0
  {
1768
0
    libcerror_error_set(
1769
0
     error,
1770
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1771
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1772
0
     "%s: invalid sub file entry value already set.",
1773
0
     function );
1774
1775
0
    return( -1 );
1776
0
  }
1777
0
  if( internal_file_entry->directory == NULL )
1778
0
  {
1779
0
    if( libfsfat_internal_file_entry_get_directory(
1780
0
         internal_file_entry,
1781
0
         error ) != 1 )
1782
0
    {
1783
0
      libcerror_error_set(
1784
0
       error,
1785
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1786
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1787
0
       "%s: unable to determine directory.",
1788
0
       function );
1789
1790
0
      goto on_error;
1791
0
    }
1792
0
  }
1793
0
  result = libfsfat_directory_get_file_entry_by_utf16_name(
1794
0
            internal_file_entry->directory,
1795
0
            utf16_string,
1796
0
            utf16_string_length,
1797
0
            &sub_directory_entry,
1798
0
            error );
1799
1800
0
  if( result == -1 )
1801
0
  {
1802
0
    libcerror_error_set(
1803
0
     error,
1804
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1805
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1806
0
     "%s: unable to retrieve sub directory entry.",
1807
0
     function );
1808
1809
0
    goto on_error;
1810
0
  }
1811
0
  else if( result == 0 )
1812
0
  {
1813
0
    return( 0 );
1814
0
  }
1815
0
  if( libfsfat_directory_entry_get_identifier(
1816
0
       sub_directory_entry,
1817
0
       &identifier,
1818
0
       error ) != 1 )
1819
0
  {
1820
0
    libcerror_error_set(
1821
0
     error,
1822
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1823
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1824
0
     "%s: unable to retrieve identifier from sub directory entry.",
1825
0
     function );
1826
1827
0
    goto on_error;
1828
0
  }
1829
0
  if( libfsfat_directory_entry_clone(
1830
0
       &safe_directory_entry,
1831
0
       sub_directory_entry,
1832
0
       error ) != 1 )
1833
0
  {
1834
0
    libcerror_error_set(
1835
0
     error,
1836
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1837
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1838
0
     "%s: unable to create sub directory entry.",
1839
0
     function );
1840
1841
0
    goto on_error;
1842
0
  }
1843
  /* libfsfat_file_entry_initialize takes over management of safe_directory_entry
1844
   */
1845
0
  if( libfsfat_file_entry_initialize(
1846
0
       sub_file_entry,
1847
0
       internal_file_entry->io_handle,
1848
0
       internal_file_entry->file_io_handle,
1849
0
       internal_file_entry->file_system,
1850
0
       identifier,
1851
0
       safe_directory_entry,
1852
0
       NULL,
1853
0
       error ) != 1 )
1854
0
  {
1855
0
    libcerror_error_set(
1856
0
     error,
1857
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1858
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1859
0
     "%s: unable to create file entry.",
1860
0
     function );
1861
1862
0
    goto on_error;
1863
0
  }
1864
0
  return( 1 );
1865
1866
0
on_error:
1867
0
  if( safe_directory_entry != NULL )
1868
0
  {
1869
0
    libfsfat_directory_entry_free(
1870
0
     &safe_directory_entry,
1871
0
     NULL );
1872
0
  }
1873
0
  return( -1 );
1874
0
}
1875
1876
/* Retrieves the sub file entry for an UTF-16 encoded name
1877
 * Returns 1 if successful, 0 if no such file entry or -1 on error
1878
 */
1879
int libfsfat_file_entry_get_sub_file_entry_by_utf16_name(
1880
     libfsfat_file_entry_t *file_entry,
1881
     const uint16_t *utf16_string,
1882
     size_t utf16_string_length,
1883
     libfsfat_file_entry_t **sub_file_entry,
1884
     libcerror_error_t **error )
1885
0
{
1886
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
1887
0
  static char *function                               = "libfsfat_file_entry_get_sub_file_entry_by_utf16_name";
1888
0
  int result                                          = 1;
1889
1890
0
  if( file_entry == NULL )
1891
0
  {
1892
0
    libcerror_error_set(
1893
0
     error,
1894
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1895
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1896
0
     "%s: invalid file entry.",
1897
0
     function );
1898
1899
0
    return( -1 );
1900
0
  }
1901
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
1902
1903
0
  if( sub_file_entry == NULL )
1904
0
  {
1905
0
    libcerror_error_set(
1906
0
     error,
1907
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1908
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1909
0
     "%s: invalid sub file entry.",
1910
0
     function );
1911
1912
0
    return( -1 );
1913
0
  }
1914
0
  if( *sub_file_entry != NULL )
1915
0
  {
1916
0
    libcerror_error_set(
1917
0
     error,
1918
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1919
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1920
0
     "%s: invalid sub file entry value already set.",
1921
0
     function );
1922
1923
0
    return( -1 );
1924
0
  }
1925
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1926
0
  if( libcthreads_read_write_lock_grab_for_read(
1927
0
       internal_file_entry->read_write_lock,
1928
0
       error ) != 1 )
1929
0
  {
1930
0
    libcerror_error_set(
1931
0
     error,
1932
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1933
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1934
0
     "%s: unable to grab read/write lock for reading.",
1935
0
     function );
1936
1937
0
    return( -1 );
1938
0
  }
1939
0
#endif
1940
0
  if( libfsfat_internal_file_entry_get_sub_file_entry_by_utf16_name(
1941
0
       internal_file_entry,
1942
0
       utf16_string,
1943
0
       utf16_string_length,
1944
0
       sub_file_entry,
1945
0
       error ) != 1 )
1946
0
  {
1947
0
    libcerror_error_set(
1948
0
     error,
1949
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1950
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1951
0
     "%s: unable to retrieve sub file entry.",
1952
0
     function );
1953
1954
0
    result = -1;
1955
0
  }
1956
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1957
0
  if( libcthreads_read_write_lock_release_for_read(
1958
0
       internal_file_entry->read_write_lock,
1959
0
       error ) != 1 )
1960
0
  {
1961
0
    libcerror_error_set(
1962
0
     error,
1963
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1964
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1965
0
     "%s: unable to release read/write lock for reading.",
1966
0
     function );
1967
1968
0
    return( -1 );
1969
0
  }
1970
0
#endif
1971
0
  return( result );
1972
0
}
1973
1974
/* Reads data at the current offset
1975
 * Returns the number of bytes read or -1 on error
1976
 */
1977
ssize_t libfsfat_file_entry_read_buffer(
1978
         libfsfat_file_entry_t *file_entry,
1979
         void *buffer,
1980
         size_t buffer_size,
1981
         libcerror_error_t **error )
1982
0
{
1983
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
1984
0
  static char *function                               = "libfsfat_file_entry_read_buffer";
1985
0
  ssize_t read_count                                  = 0;
1986
1987
0
  if( file_entry == NULL )
1988
0
  {
1989
0
    libcerror_error_set(
1990
0
     error,
1991
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1992
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1993
0
     "%s: invalid file entry.",
1994
0
     function );
1995
1996
0
    return( -1 );
1997
0
  }
1998
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
1999
2000
0
  if( ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_DEVICE ) != 0 )
2001
0
   && ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_DIRECTORY ) != 0 )
2002
0
   && ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_VOLUME_LABEL ) != 0 ) )
2003
0
  {
2004
0
    libcerror_error_set(
2005
0
     error,
2006
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2007
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2008
0
     "%s: invalid file entry - unsupported file attribute flags not a regular file.",
2009
0
     function );
2010
2011
0
    return( -1 );
2012
0
  }
2013
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2014
0
  if( libcthreads_read_write_lock_grab_for_write(
2015
0
       internal_file_entry->read_write_lock,
2016
0
       error ) != 1 )
2017
0
  {
2018
0
    libcerror_error_set(
2019
0
     error,
2020
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2021
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2022
0
     "%s: unable to grab read/write lock for writing.",
2023
0
     function );
2024
2025
0
    return( -1 );
2026
0
  }
2027
0
#endif
2028
0
  if( internal_file_entry->cluster_block_stream == NULL )
2029
0
  {
2030
0
    if( libfsfat_file_system_get_data_stream(
2031
0
         internal_file_entry->file_system,
2032
0
         internal_file_entry->cluster_number,
2033
0
         internal_file_entry->data_size,
2034
0
         internal_file_entry->data_extents_array,
2035
0
         &( internal_file_entry->cluster_block_stream ),
2036
0
         error ) != 1 )
2037
0
    {
2038
0
      libcerror_error_set(
2039
0
       error,
2040
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2041
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2042
0
       "%s: unable to retrieve data stream: %" PRIu32 ".",
2043
0
       function,
2044
0
       internal_file_entry->cluster_number );
2045
2046
0
      read_count = -1;
2047
0
    }
2048
0
  }
2049
0
  if( read_count != -1 )
2050
0
  {
2051
0
    read_count = libfdata_stream_read_buffer(
2052
0
                  internal_file_entry->cluster_block_stream,
2053
0
                  (intptr_t *) internal_file_entry->file_io_handle,
2054
0
                  buffer,
2055
0
                  buffer_size,
2056
0
                  0,
2057
0
                  error );
2058
2059
0
    if( read_count < 0 )
2060
0
    {
2061
0
      libcerror_error_set(
2062
0
       error,
2063
0
       LIBCERROR_ERROR_DOMAIN_IO,
2064
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2065
0
       "%s: unable to read from cluster block stream.",
2066
0
       function );
2067
2068
0
      read_count = -1;
2069
0
    }
2070
0
  }
2071
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2072
0
  if( libcthreads_read_write_lock_release_for_write(
2073
0
       internal_file_entry->read_write_lock,
2074
0
       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
0
#endif
2086
0
  return( read_count );
2087
0
}
2088
2089
/* Reads data at a specific offset
2090
 * Returns the number of bytes read or -1 on error
2091
 */
2092
ssize_t libfsfat_file_entry_read_buffer_at_offset(
2093
         libfsfat_file_entry_t *file_entry,
2094
         void *buffer,
2095
         size_t buffer_size,
2096
         off64_t offset,
2097
         libcerror_error_t **error )
2098
0
{
2099
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
2100
0
  static char *function                               = "libfsfat_file_entry_read_buffer_at_offset";
2101
0
  ssize_t read_count                                  = 0;
2102
2103
0
  if( file_entry == NULL )
2104
0
  {
2105
0
    libcerror_error_set(
2106
0
     error,
2107
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2108
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2109
0
     "%s: invalid file entry.",
2110
0
     function );
2111
2112
0
    return( -1 );
2113
0
  }
2114
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
2115
2116
0
  if( ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_DEVICE ) != 0 )
2117
0
   && ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_DIRECTORY ) != 0 )
2118
0
   && ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_VOLUME_LABEL ) != 0 ) )
2119
0
  {
2120
0
    libcerror_error_set(
2121
0
     error,
2122
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2123
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2124
0
     "%s: invalid file entry - unsupported file attribute flags not a regular file.",
2125
0
     function );
2126
2127
0
    return( -1 );
2128
0
  }
2129
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2130
0
  if( libcthreads_read_write_lock_grab_for_write(
2131
0
       internal_file_entry->read_write_lock,
2132
0
       error ) != 1 )
2133
0
  {
2134
0
    libcerror_error_set(
2135
0
     error,
2136
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2137
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2138
0
     "%s: unable to grab read/write lock for writing.",
2139
0
     function );
2140
2141
0
    return( -1 );
2142
0
  }
2143
0
#endif
2144
0
  if( internal_file_entry->cluster_block_stream == NULL )
2145
0
  {
2146
0
    if( libfsfat_file_system_get_data_stream(
2147
0
         internal_file_entry->file_system,
2148
0
         internal_file_entry->cluster_number,
2149
0
         internal_file_entry->data_size,
2150
0
         internal_file_entry->data_extents_array,
2151
0
         &( internal_file_entry->cluster_block_stream ),
2152
0
         error ) != 1 )
2153
0
    {
2154
0
      libcerror_error_set(
2155
0
       error,
2156
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2157
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2158
0
       "%s: unable to retrieve data stream: %" PRIu32 ".",
2159
0
       function,
2160
0
       internal_file_entry->cluster_number );
2161
2162
0
      read_count = -1;
2163
0
    }
2164
0
  }
2165
0
  if( read_count != -1 )
2166
0
  {
2167
0
    read_count = libfdata_stream_read_buffer_at_offset(
2168
0
                  internal_file_entry->cluster_block_stream,
2169
0
                  (intptr_t *) internal_file_entry->file_io_handle,
2170
0
                  buffer,
2171
0
                  buffer_size,
2172
0
                  offset,
2173
0
                  0,
2174
0
                  error );
2175
2176
0
    if( read_count < 0 )
2177
0
    {
2178
0
      libcerror_error_set(
2179
0
       error,
2180
0
       LIBCERROR_ERROR_DOMAIN_IO,
2181
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2182
0
       "%s: unable to read from cluster block stream.",
2183
0
       function );
2184
2185
0
      read_count = -1;
2186
0
    }
2187
0
  }
2188
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2189
0
  if( libcthreads_read_write_lock_release_for_write(
2190
0
       internal_file_entry->read_write_lock,
2191
0
       error ) != 1 )
2192
0
  {
2193
0
    libcerror_error_set(
2194
0
     error,
2195
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2196
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2197
0
     "%s: unable to release read/write lock for writing.",
2198
0
     function );
2199
2200
0
    return( -1 );
2201
0
  }
2202
0
#endif
2203
0
  return( read_count );
2204
0
}
2205
2206
/* Seeks a certain offset in the data
2207
 * Returns the offset if seek is successful or -1 on error
2208
 */
2209
off64_t libfsfat_file_entry_seek_offset(
2210
         libfsfat_file_entry_t *file_entry,
2211
         off64_t offset,
2212
         int whence,
2213
         libcerror_error_t **error )
2214
0
{
2215
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
2216
0
  static char *function                               = "libfsfat_file_entry_seek_offset";
2217
2218
0
  if( file_entry == NULL )
2219
0
  {
2220
0
    libcerror_error_set(
2221
0
     error,
2222
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2223
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2224
0
     "%s: invalid file entry.",
2225
0
     function );
2226
2227
0
    return( -1 );
2228
0
  }
2229
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
2230
2231
0
  if( ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_DEVICE ) != 0 )
2232
0
   && ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_DIRECTORY ) != 0 )
2233
0
   && ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_VOLUME_LABEL ) != 0 ) )
2234
0
  {
2235
0
    libcerror_error_set(
2236
0
     error,
2237
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2238
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2239
0
     "%s: invalid file entry - unsupported file attribute flags not a regular file.",
2240
0
     function );
2241
2242
0
    return( -1 );
2243
0
  }
2244
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2245
0
  if( libcthreads_read_write_lock_grab_for_write(
2246
0
       internal_file_entry->read_write_lock,
2247
0
       error ) != 1 )
2248
0
  {
2249
0
    libcerror_error_set(
2250
0
     error,
2251
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2252
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2253
0
     "%s: unable to grab read/write lock for writing.",
2254
0
     function );
2255
2256
0
    return( -1 );
2257
0
  }
2258
0
#endif
2259
0
  if( internal_file_entry->cluster_block_stream == NULL )
2260
0
  {
2261
0
    if( libfsfat_file_system_get_data_stream(
2262
0
         internal_file_entry->file_system,
2263
0
         internal_file_entry->cluster_number,
2264
0
         internal_file_entry->data_size,
2265
0
         internal_file_entry->data_extents_array,
2266
0
         &( internal_file_entry->cluster_block_stream ),
2267
0
         error ) != 1 )
2268
0
    {
2269
0
      libcerror_error_set(
2270
0
       error,
2271
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2272
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2273
0
       "%s: unable to retrieve data stream: %" PRIu32 ".",
2274
0
       function,
2275
0
       internal_file_entry->cluster_number );
2276
2277
0
      offset = -1;
2278
0
    }
2279
0
  }
2280
0
  if( offset != -1 )
2281
0
  {
2282
0
    offset = libfdata_stream_seek_offset(
2283
0
              internal_file_entry->cluster_block_stream,
2284
0
              offset,
2285
0
              whence,
2286
0
              error );
2287
2288
0
    if( offset == -1 )
2289
0
    {
2290
0
      libcerror_error_set(
2291
0
       error,
2292
0
       LIBCERROR_ERROR_DOMAIN_IO,
2293
0
       LIBCERROR_IO_ERROR_SEEK_FAILED,
2294
0
       "%s: unable to seek offset in cluster block stream.",
2295
0
       function );
2296
2297
0
      offset = -1;
2298
0
    }
2299
0
  }
2300
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2301
0
  if( libcthreads_read_write_lock_release_for_write(
2302
0
       internal_file_entry->read_write_lock,
2303
0
       error ) != 1 )
2304
0
  {
2305
0
    libcerror_error_set(
2306
0
     error,
2307
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2308
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2309
0
     "%s: unable to release read/write lock for writing.",
2310
0
     function );
2311
2312
0
    return( -1 );
2313
0
  }
2314
0
#endif
2315
0
  return( offset );
2316
0
}
2317
2318
/* Retrieves the current offset of the data
2319
 * Returns the offset if successful or -1 on error
2320
 */
2321
int libfsfat_file_entry_get_offset(
2322
     libfsfat_file_entry_t *file_entry,
2323
     off64_t *offset,
2324
     libcerror_error_t **error )
2325
0
{
2326
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
2327
0
  static char *function                               = "libfsfat_file_entry_get_offset";
2328
0
  int result                                          = 1;
2329
2330
0
  if( file_entry == NULL )
2331
0
  {
2332
0
    libcerror_error_set(
2333
0
     error,
2334
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2335
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2336
0
     "%s: invalid file entry.",
2337
0
     function );
2338
2339
0
    return( -1 );
2340
0
  }
2341
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
2342
2343
0
  if( ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_DEVICE ) != 0 )
2344
0
   && ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_DIRECTORY ) != 0 )
2345
0
   && ( ( internal_file_entry->file_attribute_flags & LIBFSFAT_FILE_ATTRIBUTE_FLAG_VOLUME_LABEL ) != 0 ) )
2346
0
  {
2347
0
    libcerror_error_set(
2348
0
     error,
2349
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2350
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2351
0
     "%s: invalid file entry - unsupported file attribute flags not a regular file.",
2352
0
     function );
2353
2354
0
    return( -1 );
2355
0
  }
2356
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2357
0
  if( libcthreads_read_write_lock_grab_for_read(
2358
0
       internal_file_entry->read_write_lock,
2359
0
       error ) != 1 )
2360
0
  {
2361
0
    libcerror_error_set(
2362
0
     error,
2363
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2364
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2365
0
     "%s: unable to grab read/write lock for reading.",
2366
0
     function );
2367
2368
0
    return( -1 );
2369
0
  }
2370
0
#endif
2371
0
  if( internal_file_entry->cluster_block_stream == NULL )
2372
0
  {
2373
0
    if( libfsfat_file_system_get_data_stream(
2374
0
         internal_file_entry->file_system,
2375
0
         internal_file_entry->cluster_number,
2376
0
         internal_file_entry->data_size,
2377
0
         internal_file_entry->data_extents_array,
2378
0
         &( internal_file_entry->cluster_block_stream ),
2379
0
         error ) != 1 )
2380
0
    {
2381
0
      libcerror_error_set(
2382
0
       error,
2383
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2384
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2385
0
       "%s: unable to retrieve data stream: %" PRIu32 ".",
2386
0
       function,
2387
0
       internal_file_entry->cluster_number );
2388
2389
0
      result = -1;
2390
0
    }
2391
0
  }
2392
0
  if( result != -1 )
2393
0
  {
2394
0
    if( libfdata_stream_get_offset(
2395
0
         internal_file_entry->cluster_block_stream,
2396
0
         offset,
2397
0
         error ) != 1 )
2398
0
    {
2399
0
      libcerror_error_set(
2400
0
       error,
2401
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2402
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2403
0
       "%s: unable to retrieve offset from cluster block stream.",
2404
0
       function );
2405
2406
0
      result = -1;
2407
0
    }
2408
0
  }
2409
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2410
0
  if( libcthreads_read_write_lock_release_for_read(
2411
0
       internal_file_entry->read_write_lock,
2412
0
       error ) != 1 )
2413
0
  {
2414
0
    libcerror_error_set(
2415
0
     error,
2416
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2417
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2418
0
     "%s: unable to release read/write lock for reading.",
2419
0
     function );
2420
2421
0
    return( -1 );
2422
0
  }
2423
0
#endif
2424
0
  return( result );
2425
0
}
2426
2427
/* Retrieves the size of the data
2428
 * Returns 1 if successful or -1 on error
2429
 */
2430
int libfsfat_file_entry_get_size(
2431
     libfsfat_file_entry_t *file_entry,
2432
     size64_t *size,
2433
     libcerror_error_t **error )
2434
0
{
2435
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
2436
0
  static char *function                               = "libfsfat_file_entry_get_size";
2437
2438
0
  if( file_entry == NULL )
2439
0
  {
2440
0
    libcerror_error_set(
2441
0
     error,
2442
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2443
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2444
0
     "%s: invalid file entry.",
2445
0
     function );
2446
2447
0
    return( -1 );
2448
0
  }
2449
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
2450
2451
0
  if( size == NULL )
2452
0
  {
2453
0
    libcerror_error_set(
2454
0
     error,
2455
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2456
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2457
0
     "%s: invalid size.",
2458
0
     function );
2459
2460
0
    return( -1 );
2461
0
  }
2462
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2463
0
  if( libcthreads_read_write_lock_grab_for_read(
2464
0
       internal_file_entry->read_write_lock,
2465
0
       error ) != 1 )
2466
0
  {
2467
0
    libcerror_error_set(
2468
0
     error,
2469
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2470
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2471
0
     "%s: unable to grab read/write lock for reading.",
2472
0
     function );
2473
2474
0
    return( -1 );
2475
0
  }
2476
0
#endif
2477
0
  *size = internal_file_entry->data_size;
2478
2479
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2480
0
  if( libcthreads_read_write_lock_release_for_read(
2481
0
       internal_file_entry->read_write_lock,
2482
0
       error ) != 1 )
2483
0
  {
2484
0
    libcerror_error_set(
2485
0
     error,
2486
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2487
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2488
0
     "%s: unable to release read/write lock for reading.",
2489
0
     function );
2490
2491
0
    return( -1 );
2492
0
  }
2493
0
#endif
2494
0
  return( 1 );
2495
0
}
2496
2497
/* Retrieves the number of extents of the data
2498
 * Returns 1 if successful or -1 on error
2499
 */
2500
int libfsfat_file_entry_get_number_of_extents(
2501
     libfsfat_file_entry_t *file_entry,
2502
     int *number_of_extents,
2503
     libcerror_error_t **error )
2504
0
{
2505
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
2506
0
  static char *function                               = "libfsfat_file_entry_get_number_of_extents";
2507
0
  int result                                           = 1;
2508
2509
0
  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
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
2521
2522
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2523
0
  if( libcthreads_read_write_lock_grab_for_read(
2524
0
       internal_file_entry->read_write_lock,
2525
0
       error ) != 1 )
2526
0
  {
2527
0
    libcerror_error_set(
2528
0
     error,
2529
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2530
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2531
0
     "%s: unable to grab read/write lock for reading.",
2532
0
     function );
2533
2534
0
    return( -1 );
2535
0
  }
2536
0
#endif
2537
0
  if( internal_file_entry->cluster_block_stream == NULL )
2538
0
  {
2539
0
    if( libfsfat_file_system_get_data_stream(
2540
0
         internal_file_entry->file_system,
2541
0
         internal_file_entry->cluster_number,
2542
0
         internal_file_entry->data_size,
2543
0
         internal_file_entry->data_extents_array,
2544
0
         &( internal_file_entry->cluster_block_stream ),
2545
0
         error ) != 1 )
2546
0
    {
2547
0
      libcerror_error_set(
2548
0
       error,
2549
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2550
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2551
0
       "%s: unable to retrieve data stream: %" PRIu32 ".",
2552
0
       function,
2553
0
       internal_file_entry->cluster_number );
2554
2555
0
      result = -1;
2556
0
    }
2557
0
  }
2558
0
  if( result != -1 )
2559
0
  {
2560
0
    if( libcdata_array_get_number_of_entries(
2561
0
         internal_file_entry->data_extents_array,
2562
0
         number_of_extents,
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 retrieve number of segments from cluster block stream.",
2570
0
       function );
2571
2572
0
      result = -1;
2573
0
    }
2574
0
  }
2575
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2576
0
  if( libcthreads_read_write_lock_release_for_read(
2577
0
       internal_file_entry->read_write_lock,
2578
0
       error ) != 1 )
2579
0
  {
2580
0
    libcerror_error_set(
2581
0
     error,
2582
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2583
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2584
0
     "%s: unable to release read/write lock for reading.",
2585
0
     function );
2586
2587
0
    return( -1 );
2588
0
  }
2589
0
#endif
2590
0
  return( result );
2591
0
}
2592
2593
/* Retrieves a specific extent of the data
2594
 * Returns 1 if successful or -1 on error
2595
 */
2596
int libfsfat_file_entry_get_extent_by_index(
2597
     libfsfat_file_entry_t *file_entry,
2598
     int extent_index,
2599
     off64_t *extent_offset,
2600
     size64_t *extent_size,
2601
     uint32_t *extent_flags,
2602
     libcerror_error_t **error )
2603
0
{
2604
0
  libfsfat_extent_t *extent                           = NULL;
2605
0
  libfsfat_internal_file_entry_t *internal_file_entry = NULL;
2606
0
  static char *function                               = "libfsfat_file_entry_get_extent_by_index";
2607
0
  int result                                          = 1;
2608
2609
0
  if( file_entry == NULL )
2610
0
  {
2611
0
    libcerror_error_set(
2612
0
     error,
2613
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2614
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2615
0
     "%s: invalid file entry.",
2616
0
     function );
2617
2618
0
    return( -1 );
2619
0
  }
2620
0
  internal_file_entry = (libfsfat_internal_file_entry_t *) file_entry;
2621
2622
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2623
0
  if( libcthreads_read_write_lock_grab_for_read(
2624
0
       internal_file_entry->read_write_lock,
2625
0
       error ) != 1 )
2626
0
  {
2627
0
    libcerror_error_set(
2628
0
     error,
2629
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2630
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2631
0
     "%s: unable to grab read/write lock for reading.",
2632
0
     function );
2633
2634
0
    return( -1 );
2635
0
  }
2636
0
#endif
2637
0
  if( internal_file_entry->cluster_block_stream == NULL )
2638
0
  {
2639
0
    if( libfsfat_file_system_get_data_stream(
2640
0
         internal_file_entry->file_system,
2641
0
         internal_file_entry->cluster_number,
2642
0
         internal_file_entry->data_size,
2643
0
         internal_file_entry->data_extents_array,
2644
0
         &( internal_file_entry->cluster_block_stream ),
2645
0
         error ) != 1 )
2646
0
    {
2647
0
      libcerror_error_set(
2648
0
       error,
2649
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2650
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2651
0
       "%s: unable to retrieve data stream: %" PRIu32 ".",
2652
0
       function,
2653
0
       internal_file_entry->cluster_number );
2654
2655
0
      result = -1;
2656
0
    }
2657
0
  }
2658
0
  if( result != -1 )
2659
0
  {
2660
0
    if( libcdata_array_get_entry_by_index(
2661
0
         internal_file_entry->data_extents_array,
2662
0
         extent_index,
2663
0
         (intptr_t **) &extent,
2664
0
         error ) != 1 )
2665
0
    {
2666
0
      libcerror_error_set(
2667
0
       error,
2668
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2669
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2670
0
       "%s: unable to retrieve segment: %d from cluster block stream.",
2671
0
       function,
2672
0
       extent_index );
2673
2674
0
      result = -1;
2675
0
    }
2676
0
    if( result == 1 )
2677
0
    {
2678
0
      if( libfsfat_extent_get_values(
2679
0
           extent,
2680
0
           extent_offset,
2681
0
           extent_size,
2682
0
           extent_flags,
2683
0
           error ) != 1 )
2684
0
      {
2685
0
        libcerror_error_set(
2686
0
         error,
2687
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2688
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2689
0
         "%s: unable to retrieve extent: %d values.",
2690
0
         function,
2691
0
         extent_index );
2692
2693
0
        result = -1;
2694
0
      }
2695
0
    }
2696
0
  }
2697
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
2698
0
  if( libcthreads_read_write_lock_release_for_read(
2699
0
       internal_file_entry->read_write_lock,
2700
0
       error ) != 1 )
2701
0
  {
2702
0
    libcerror_error_set(
2703
0
     error,
2704
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2705
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2706
0
     "%s: unable to release read/write lock for reading.",
2707
0
     function );
2708
2709
0
    return( -1 );
2710
0
  }
2711
0
#endif
2712
0
  return( result );
2713
0
}
2714