Coverage Report

Created: 2026-04-10 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsfat/libfsfat/libfsfat_volume.c
Line
Count
Source
1
/*
2
 * Volume functions
3
 *
4
 * Copyright (C) 2021-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 <narrow_string.h>
25
#include <types.h>
26
#include <wide_string.h>
27
28
#include "libfsfat_boot_record.h"
29
#include "libfsfat_debug.h"
30
#include "libfsfat_definitions.h"
31
#include "libfsfat_file_entry.h"
32
#include "libfsfat_io_handle.h"
33
#include "libfsfat_libcerror.h"
34
#include "libfsfat_libcnotify.h"
35
#include "libfsfat_libcthreads.h"
36
#include "libfsfat_volume.h"
37
38
/* Creates a volume
39
 * Make sure the value volume is referencing, is set to NULL
40
 * Returns 1 if successful or -1 on error
41
 */
42
int libfsfat_volume_initialize(
43
     libfsfat_volume_t **volume,
44
     libcerror_error_t **error )
45
2.46k
{
46
2.46k
  libfsfat_internal_volume_t *internal_volume = NULL;
47
2.46k
  static char *function                       = "libfsfat_volume_initialize";
48
49
2.46k
  if( volume == NULL )
50
0
  {
51
0
    libcerror_error_set(
52
0
     error,
53
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
54
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
55
0
     "%s: invalid volume.",
56
0
     function );
57
58
0
    return( -1 );
59
0
  }
60
2.46k
  if( *volume != NULL )
61
0
  {
62
0
    libcerror_error_set(
63
0
     error,
64
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
65
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
66
0
     "%s: invalid volume value already set.",
67
0
     function );
68
69
0
    return( -1 );
70
0
  }
71
2.46k
  internal_volume = memory_allocate_structure(
72
2.46k
                     libfsfat_internal_volume_t );
73
74
2.46k
  if( internal_volume == NULL )
75
0
  {
76
0
    libcerror_error_set(
77
0
     error,
78
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
79
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
80
0
     "%s: unable to create volume.",
81
0
     function );
82
83
0
    goto on_error;
84
0
  }
85
2.46k
  if( memory_set(
86
2.46k
       internal_volume,
87
2.46k
       0,
88
2.46k
       sizeof( libfsfat_internal_volume_t ) ) == NULL )
89
0
  {
90
0
    libcerror_error_set(
91
0
     error,
92
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
93
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
94
0
     "%s: unable to clear volume.",
95
0
     function );
96
97
0
    memory_free(
98
0
     internal_volume );
99
100
0
    return( -1 );
101
0
  }
102
2.46k
  if( libfsfat_io_handle_initialize(
103
2.46k
       &( internal_volume->io_handle ),
104
2.46k
       error ) != 1 )
105
0
  {
106
0
    libcerror_error_set(
107
0
     error,
108
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
109
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
110
0
     "%s: unable to create IO handle.",
111
0
     function );
112
113
0
    goto on_error;
114
0
  }
115
2.46k
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
116
2.46k
  if( libcthreads_read_write_lock_initialize(
117
2.46k
       &( internal_volume->read_write_lock ),
118
2.46k
       error ) != 1 )
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 initialize read/write lock.",
125
0
     function );
126
127
0
    goto on_error;
128
0
  }
129
2.46k
#endif
130
2.46k
  *volume = (libfsfat_volume_t *) internal_volume;
131
132
2.46k
  return( 1 );
133
134
0
on_error:
135
0
  if( internal_volume != NULL )
136
0
  {
137
0
    if( internal_volume->io_handle != NULL )
138
0
    {
139
0
      libfsfat_io_handle_free(
140
0
       &( internal_volume->io_handle ),
141
0
       NULL );
142
0
    }
143
0
    memory_free(
144
0
     internal_volume );
145
0
  }
146
0
  return( -1 );
147
2.46k
}
148
149
/* Frees a volume
150
 * Returns 1 if successful or -1 on error
151
 */
152
int libfsfat_volume_free(
153
     libfsfat_volume_t **volume,
154
     libcerror_error_t **error )
155
2.46k
{
156
2.46k
  libfsfat_internal_volume_t *internal_volume = NULL;
157
2.46k
  static char *function                       = "libfsfat_volume_free";
158
2.46k
  int result                                  = 1;
159
160
2.46k
  if( volume == NULL )
161
0
  {
162
0
    libcerror_error_set(
163
0
     error,
164
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
165
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
166
0
     "%s: invalid volume.",
167
0
     function );
168
169
0
    return( -1 );
170
0
  }
171
2.46k
  if( *volume != NULL )
172
2.46k
  {
173
2.46k
    internal_volume = (libfsfat_internal_volume_t *) *volume;
174
175
2.46k
    if( internal_volume->file_io_handle != NULL )
176
0
    {
177
0
      if( libfsfat_volume_close(
178
0
           *volume,
179
0
           error ) != 0 )
180
0
      {
181
0
        libcerror_error_set(
182
0
         error,
183
0
         LIBCERROR_ERROR_DOMAIN_IO,
184
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
185
0
         "%s: unable to close volume.",
186
0
         function );
187
188
0
        result = -1;
189
0
      }
190
0
    }
191
2.46k
    *volume = NULL;
192
193
2.46k
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
194
2.46k
    if( libcthreads_read_write_lock_free(
195
2.46k
         &( internal_volume->read_write_lock ),
196
2.46k
         error ) != 1 )
197
0
    {
198
0
      libcerror_error_set(
199
0
       error,
200
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
201
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
202
0
       "%s: unable to free read/write lock.",
203
0
       function );
204
205
0
      result = -1;
206
0
    }
207
2.46k
#endif
208
2.46k
    if( libfsfat_io_handle_free(
209
2.46k
         &( internal_volume->io_handle ),
210
2.46k
         error ) != 1 )
211
0
    {
212
0
      libcerror_error_set(
213
0
       error,
214
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
215
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
216
0
       "%s: unable to free IO handle.",
217
0
       function );
218
219
0
      result = -1;
220
0
    }
221
2.46k
    memory_free(
222
2.46k
     internal_volume );
223
2.46k
  }
224
2.46k
  return( result );
225
2.46k
}
226
227
/* Signals the volume to abort its current activity
228
 * Returns 1 if successful or -1 on error
229
 */
230
int libfsfat_volume_signal_abort(
231
     libfsfat_volume_t *volume,
232
     libcerror_error_t **error )
233
0
{
234
0
  libfsfat_internal_volume_t *internal_volume = NULL;
235
0
  static char *function                       = "libfsfat_volume_signal_abort";
236
237
0
  if( volume == NULL )
238
0
  {
239
0
    libcerror_error_set(
240
0
     error,
241
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
242
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
243
0
     "%s: invalid volume.",
244
0
     function );
245
246
0
    return( -1 );
247
0
  }
248
0
  internal_volume = (libfsfat_internal_volume_t *) volume;
249
250
0
  if( internal_volume->io_handle == NULL )
251
0
  {
252
0
    libcerror_error_set(
253
0
     error,
254
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
255
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
256
0
     "%s: invalid volume - missing IO handle.",
257
0
     function );
258
259
0
    return( -1 );
260
0
  }
261
0
  internal_volume->io_handle->abort = 1;
262
263
0
  return( 1 );
264
0
}
265
266
/* Opens a volume
267
 * Returns 1 if successful or -1 on error
268
 */
269
int libfsfat_volume_open(
270
     libfsfat_volume_t *volume,
271
     const char *filename,
272
     int access_flags,
273
     libcerror_error_t **error )
274
0
{
275
0
  libbfio_handle_t *file_io_handle            = NULL;
276
0
  libfsfat_internal_volume_t *internal_volume = NULL;
277
0
  static char *function                       = "libfsfat_volume_open";
278
279
0
  if( volume == NULL )
280
0
  {
281
0
    libcerror_error_set(
282
0
     error,
283
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
284
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
285
0
     "%s: invalid volume.",
286
0
     function );
287
288
0
    return( -1 );
289
0
  }
290
0
  internal_volume = (libfsfat_internal_volume_t *) volume;
291
292
0
  if( filename == NULL )
293
0
  {
294
0
    libcerror_error_set(
295
0
     error,
296
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
297
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
298
0
     "%s: invalid filename.",
299
0
     function );
300
301
0
    return( -1 );
302
0
  }
303
0
  if( ( ( access_flags & LIBFSFAT_ACCESS_FLAG_READ ) == 0 )
304
0
   && ( ( access_flags & LIBFSFAT_ACCESS_FLAG_WRITE ) == 0 ) )
305
0
  {
306
0
    libcerror_error_set(
307
0
     error,
308
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
309
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
310
0
     "%s: unsupported access flags.",
311
0
     function );
312
313
0
    return( -1 );
314
0
  }
315
0
  if( ( access_flags & LIBFSFAT_ACCESS_FLAG_WRITE ) != 0 )
316
0
  {
317
0
    libcerror_error_set(
318
0
     error,
319
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
320
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
321
0
     "%s: write access currently not supported.",
322
0
     function );
323
324
0
    return( -1 );
325
0
  }
326
0
  if( libbfio_file_initialize(
327
0
       &file_io_handle,
328
0
       error ) != 1 )
329
0
  {
330
0
    libcerror_error_set(
331
0
     error,
332
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
333
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
334
0
     "%s: unable to create file IO handle.",
335
0
     function );
336
337
0
    goto on_error;
338
0
  }
339
#if defined( HAVE_DEBUG_OUTPUT )
340
  if( libbfio_handle_set_track_offsets_read(
341
       file_io_handle,
342
       1,
343
       error ) != 1 )
344
  {
345
    libcerror_error_set(
346
     error,
347
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
348
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
349
     "%s: unable to set track offsets read in file IO handle.",
350
     function );
351
352
    goto on_error;
353
  }
354
#endif
355
0
  if( libbfio_file_set_name(
356
0
       file_io_handle,
357
0
       filename,
358
0
       narrow_string_length(
359
0
        filename ) + 1,
360
0
       error ) != 1 )
361
0
  {
362
0
    libcerror_error_set(
363
0
     error,
364
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
365
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
366
0
     "%s: unable to set filename in file IO handle.",
367
0
     function );
368
369
0
    goto on_error;
370
0
  }
371
0
  if( libfsfat_volume_open_file_io_handle(
372
0
       volume,
373
0
       file_io_handle,
374
0
       access_flags,
375
0
       error ) != 1 )
376
0
  {
377
0
    libcerror_error_set(
378
0
     error,
379
0
     LIBCERROR_ERROR_DOMAIN_IO,
380
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
381
0
     "%s: unable to open volume: %s.",
382
0
     function,
383
0
     filename );
384
385
0
    goto on_error;
386
0
  }
387
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
388
0
  if( libcthreads_read_write_lock_grab_for_write(
389
0
       internal_volume->read_write_lock,
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_SET_FAILED,
396
0
     "%s: unable to grab read/write lock for writing.",
397
0
     function );
398
399
0
    goto on_error;
400
0
  }
401
0
#endif
402
0
  internal_volume->file_io_handle_created_in_library = 1;
403
404
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
405
0
  if( libcthreads_read_write_lock_release_for_write(
406
0
       internal_volume->read_write_lock,
407
0
       error ) != 1 )
408
0
  {
409
0
    libcerror_error_set(
410
0
     error,
411
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
412
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
413
0
     "%s: unable to release read/write lock for writing.",
414
0
     function );
415
416
0
    internal_volume->file_io_handle_created_in_library = 0;
417
418
0
    goto on_error;
419
0
  }
420
0
#endif
421
0
  return( 1 );
422
423
0
on_error:
424
0
  if( file_io_handle != NULL )
425
0
  {
426
0
    libbfio_handle_free(
427
0
     &file_io_handle,
428
0
     NULL );
429
0
  }
430
0
  return( -1 );
431
0
}
432
433
#if defined( HAVE_WIDE_CHARACTER_TYPE )
434
435
/* Opens a volume
436
 * Returns 1 if successful or -1 on error
437
 */
438
int libfsfat_volume_open_wide(
439
     libfsfat_volume_t *volume,
440
     const wchar_t *filename,
441
     int access_flags,
442
     libcerror_error_t **error )
443
{
444
  libbfio_handle_t *file_io_handle            = NULL;
445
  libfsfat_internal_volume_t *internal_volume = NULL;
446
  static char *function                       = "libfsfat_volume_open_wide";
447
448
  if( volume == NULL )
449
  {
450
    libcerror_error_set(
451
     error,
452
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
453
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
454
     "%s: invalid volume.",
455
     function );
456
457
    return( -1 );
458
  }
459
  internal_volume = (libfsfat_internal_volume_t *) volume;
460
461
  if( filename == NULL )
462
  {
463
    libcerror_error_set(
464
     error,
465
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
466
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
467
     "%s: invalid filename.",
468
     function );
469
470
    return( -1 );
471
  }
472
  if( ( ( access_flags & LIBFSFAT_ACCESS_FLAG_READ ) == 0 )
473
   && ( ( access_flags & LIBFSFAT_ACCESS_FLAG_WRITE ) == 0 ) )
474
  {
475
    libcerror_error_set(
476
     error,
477
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
478
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
479
     "%s: unsupported access flags.",
480
     function );
481
482
    return( -1 );
483
  }
484
  if( ( access_flags & LIBFSFAT_ACCESS_FLAG_WRITE ) != 0 )
485
  {
486
    libcerror_error_set(
487
     error,
488
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
489
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
490
     "%s: write access currently not supported.",
491
     function );
492
493
    return( -1 );
494
  }
495
  if( libbfio_file_initialize(
496
       &file_io_handle,
497
       error ) != 1 )
498
  {
499
    libcerror_error_set(
500
     error,
501
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
502
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
503
     "%s: unable to create file IO handle.",
504
     function );
505
506
    goto on_error;
507
  }
508
#if defined( HAVE_DEBUG_OUTPUT )
509
  if( libbfio_handle_set_track_offsets_read(
510
       file_io_handle,
511
       1,
512
       error ) != 1 )
513
  {
514
    libcerror_error_set(
515
     error,
516
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
517
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
518
     "%s: unable to set track offsets read in file IO handle.",
519
     function );
520
521
    goto on_error;
522
  }
523
#endif
524
  if( libbfio_file_set_name_wide(
525
       file_io_handle,
526
       filename,
527
       wide_string_length(
528
        filename ) + 1,
529
       error ) != 1 )
530
  {
531
    libcerror_error_set(
532
     error,
533
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
534
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
535
     "%s: unable to set filename in file IO handle.",
536
     function );
537
538
    goto on_error;
539
  }
540
  if( libfsfat_volume_open_file_io_handle(
541
       volume,
542
       file_io_handle,
543
       access_flags,
544
       error ) != 1 )
545
  {
546
    libcerror_error_set(
547
     error,
548
     LIBCERROR_ERROR_DOMAIN_IO,
549
     LIBCERROR_IO_ERROR_OPEN_FAILED,
550
     "%s: unable to open volume: %ls.",
551
     function,
552
     filename );
553
554
    goto on_error;
555
  }
556
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
557
  if( libcthreads_read_write_lock_grab_for_write(
558
       internal_volume->read_write_lock,
559
       error ) != 1 )
560
  {
561
    libcerror_error_set(
562
     error,
563
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
564
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
565
     "%s: unable to grab read/write lock for writing.",
566
     function );
567
568
    goto on_error;
569
  }
570
#endif
571
  internal_volume->file_io_handle_created_in_library = 1;
572
573
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
574
  if( libcthreads_read_write_lock_release_for_write(
575
       internal_volume->read_write_lock,
576
       error ) != 1 )
577
  {
578
    libcerror_error_set(
579
     error,
580
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
581
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
582
     "%s: unable to release read/write lock for writing.",
583
     function );
584
585
    internal_volume->file_io_handle_created_in_library = 0;
586
587
    goto on_error;
588
  }
589
#endif
590
  return( 1 );
591
592
on_error:
593
  if( file_io_handle != NULL )
594
  {
595
    libbfio_handle_free(
596
     &file_io_handle,
597
     NULL );
598
  }
599
  return( -1 );
600
}
601
602
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
603
604
/* Opens a volume using a Basic File IO (bfio) handle
605
 * Returns 1 if successful or -1 on error
606
 */
607
int libfsfat_volume_open_file_io_handle(
608
     libfsfat_volume_t *volume,
609
     libbfio_handle_t *file_io_handle,
610
     int access_flags,
611
     libcerror_error_t **error )
612
2.46k
{
613
2.46k
  libfsfat_internal_volume_t *internal_volume = NULL;
614
2.46k
  static char *function                       = "libfsfat_volume_open_file_io_handle";
615
2.46k
  uint8_t file_io_handle_opened_in_library    = 0;
616
2.46k
  int bfio_access_flags                       = 0;
617
2.46k
  int file_io_handle_is_open                  = 0;
618
619
2.46k
  if( volume == NULL )
620
0
  {
621
0
    libcerror_error_set(
622
0
     error,
623
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
624
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
625
0
     "%s: invalid volume.",
626
0
     function );
627
628
0
    return( -1 );
629
0
  }
630
2.46k
  internal_volume = (libfsfat_internal_volume_t *) volume;
631
632
2.46k
  if( internal_volume->file_io_handle != NULL )
633
0
  {
634
0
    libcerror_error_set(
635
0
     error,
636
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
637
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
638
0
     "%s: invalid volume - file IO handle already set.",
639
0
     function );
640
641
0
    return( -1 );
642
0
  }
643
2.46k
  if( file_io_handle == NULL )
644
0
  {
645
0
    libcerror_error_set(
646
0
     error,
647
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
648
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
649
0
     "%s: invalid file IO handle.",
650
0
     function );
651
652
0
    return( -1 );
653
0
  }
654
2.46k
  if( ( ( access_flags & LIBFSFAT_ACCESS_FLAG_READ ) == 0 )
655
0
   && ( ( access_flags & LIBFSFAT_ACCESS_FLAG_WRITE ) == 0 ) )
656
0
  {
657
0
    libcerror_error_set(
658
0
     error,
659
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
660
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
661
0
     "%s: unsupported access flags.",
662
0
     function );
663
664
0
    return( -1 );
665
0
  }
666
2.46k
  if( ( access_flags & LIBFSFAT_ACCESS_FLAG_WRITE ) != 0 )
667
0
  {
668
0
    libcerror_error_set(
669
0
     error,
670
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
671
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
672
0
     "%s: write access currently not supported.",
673
0
     function );
674
675
0
    return( -1 );
676
0
  }
677
2.46k
  if( ( access_flags & LIBFSFAT_ACCESS_FLAG_READ ) != 0 )
678
2.46k
  {
679
2.46k
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
680
2.46k
  }
681
2.46k
  file_io_handle_is_open = libbfio_handle_is_open(
682
2.46k
                            file_io_handle,
683
2.46k
                            error );
684
685
2.46k
  if( file_io_handle_is_open == -1 )
686
0
  {
687
0
    libcerror_error_set(
688
0
     error,
689
0
     LIBCERROR_ERROR_DOMAIN_IO,
690
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
691
0
     "%s: unable to open volume.",
692
0
     function );
693
694
0
    goto on_error;
695
0
  }
696
2.46k
  else if( file_io_handle_is_open == 0 )
697
2.46k
  {
698
2.46k
    if( libbfio_handle_open(
699
2.46k
         file_io_handle,
700
2.46k
         bfio_access_flags,
701
2.46k
         error ) != 1 )
702
0
    {
703
0
      libcerror_error_set(
704
0
       error,
705
0
       LIBCERROR_ERROR_DOMAIN_IO,
706
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
707
0
       "%s: unable to open file IO handle.",
708
0
       function );
709
710
0
      goto on_error;
711
0
    }
712
2.46k
    file_io_handle_opened_in_library = 1;
713
2.46k
  }
714
2.46k
  if( libfsfat_internal_volume_open_read(
715
2.46k
       internal_volume,
716
2.46k
       file_io_handle,
717
2.46k
       error ) != 1 )
718
2.15k
  {
719
2.15k
    libcerror_error_set(
720
2.15k
     error,
721
2.15k
     LIBCERROR_ERROR_DOMAIN_IO,
722
2.15k
     LIBCERROR_IO_ERROR_READ_FAILED,
723
2.15k
     "%s: unable to read from file IO handle.",
724
2.15k
     function );
725
726
2.15k
    goto on_error;
727
2.15k
  }
728
308
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
729
308
  if( libcthreads_read_write_lock_grab_for_write(
730
308
       internal_volume->read_write_lock,
731
308
       error ) != 1 )
732
0
  {
733
0
    libcerror_error_set(
734
0
     error,
735
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
736
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
737
0
     "%s: unable to grab read/write lock for writing.",
738
0
     function );
739
740
0
    goto on_error;
741
0
  }
742
308
#endif
743
308
  internal_volume->file_io_handle                   = file_io_handle;
744
308
  internal_volume->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
745
746
308
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
747
308
  if( libcthreads_read_write_lock_release_for_write(
748
308
       internal_volume->read_write_lock,
749
308
       error ) != 1 )
750
0
  {
751
0
    libcerror_error_set(
752
0
     error,
753
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
754
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
755
0
     "%s: unable to release read/write lock for writing.",
756
0
     function );
757
758
0
    internal_volume->file_io_handle                   = NULL;
759
0
    internal_volume->file_io_handle_opened_in_library = 0;
760
761
0
    goto on_error;
762
0
  }
763
308
#endif
764
308
  return( 1 );
765
766
2.15k
on_error:
767
2.15k
  if( file_io_handle_opened_in_library != 0 )
768
2.15k
  {
769
2.15k
    libbfio_handle_close(
770
2.15k
     file_io_handle,
771
2.15k
     error );
772
2.15k
  }
773
2.15k
  return( -1 );
774
308
}
775
776
/* Closes a volume
777
 * Returns 0 if successful or -1 on error
778
 */
779
int libfsfat_volume_close(
780
     libfsfat_volume_t *volume,
781
     libcerror_error_t **error )
782
308
{
783
308
  libfsfat_internal_volume_t *internal_volume = NULL;
784
308
  static char *function                       = "libfsfat_volume_close";
785
308
  int result                                  = 0;
786
787
308
  if( volume == NULL )
788
0
  {
789
0
    libcerror_error_set(
790
0
     error,
791
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
792
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
793
0
     "%s: invalid volume.",
794
0
     function );
795
796
0
    return( -1 );
797
0
  }
798
308
  internal_volume = (libfsfat_internal_volume_t *) volume;
799
800
308
  if( internal_volume->file_io_handle == NULL )
801
0
  {
802
0
    libcerror_error_set(
803
0
     error,
804
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
805
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
806
0
     "%s: invalid volume - missing file IO handle.",
807
0
     function );
808
809
0
    return( -1 );
810
0
  }
811
308
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
812
308
  if( libcthreads_read_write_lock_grab_for_write(
813
308
       internal_volume->read_write_lock,
814
308
       error ) != 1 )
815
0
  {
816
0
    libcerror_error_set(
817
0
     error,
818
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
819
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
820
0
     "%s: unable to grab read/write lock for writing.",
821
0
     function );
822
823
0
    return( -1 );
824
0
  }
825
308
#endif
826
#if defined( HAVE_DEBUG_OUTPUT )
827
  if( libcnotify_verbose != 0 )
828
  {
829
    if( internal_volume->file_io_handle_created_in_library != 0 )
830
    {
831
      if( libfsfat_debug_print_read_offsets(
832
           internal_volume->file_io_handle,
833
           error ) != 1 )
834
      {
835
        libcerror_error_set(
836
         error,
837
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
838
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
839
         "%s: unable to print the read offsets.",
840
         function );
841
842
        result = -1;
843
      }
844
    }
845
  }
846
#endif
847
308
  if( internal_volume->file_io_handle_opened_in_library != 0 )
848
308
  {
849
308
    if( libbfio_handle_close(
850
308
         internal_volume->file_io_handle,
851
308
         error ) != 0 )
852
0
    {
853
0
      libcerror_error_set(
854
0
       error,
855
0
       LIBCERROR_ERROR_DOMAIN_IO,
856
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
857
0
       "%s: unable to close file IO handle.",
858
0
       function );
859
860
0
      result = -1;
861
0
    }
862
308
    internal_volume->file_io_handle_opened_in_library = 0;
863
308
  }
864
308
  if( internal_volume->file_io_handle_created_in_library != 0 )
865
0
  {
866
0
    if( libbfio_handle_free(
867
0
         &( internal_volume->file_io_handle ),
868
0
         error ) != 1 )
869
0
    {
870
0
      libcerror_error_set(
871
0
       error,
872
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
873
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
874
0
       "%s: unable to free file IO handle.",
875
0
       function );
876
877
0
      result = -1;
878
0
    }
879
0
    internal_volume->file_io_handle_created_in_library = 0;
880
0
  }
881
308
  internal_volume->file_io_handle = NULL;
882
883
308
  if( libfsfat_io_handle_clear(
884
308
       internal_volume->io_handle,
885
308
       error ) != 1 )
886
0
  {
887
0
    libcerror_error_set(
888
0
     error,
889
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
890
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
891
0
     "%s: unable to clear IO handle.",
892
0
     function );
893
894
0
    result = -1;
895
0
  }
896
308
  if( internal_volume->file_system != NULL )
897
308
  {
898
308
    if( libfsfat_file_system_free(
899
308
         &( internal_volume->file_system ),
900
308
         error ) != 1 )
901
0
    {
902
0
      libcerror_error_set(
903
0
       error,
904
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
905
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
906
0
       "%s: unable to free file system.",
907
0
       function );
908
909
0
      result = -1;
910
0
    }
911
308
  }
912
308
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
913
308
  if( libcthreads_read_write_lock_release_for_write(
914
308
       internal_volume->read_write_lock,
915
308
       error ) != 1 )
916
0
  {
917
0
    libcerror_error_set(
918
0
     error,
919
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
920
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
921
0
     "%s: unable to release read/write lock for writing.",
922
0
     function );
923
924
0
    return( -1 );
925
0
  }
926
308
#endif
927
308
  return( result );
928
308
}
929
930
/* Opens a volume for reading
931
 * Returns 1 if successful or -1 on error
932
 */
933
int libfsfat_internal_volume_open_read(
934
     libfsfat_internal_volume_t *internal_volume,
935
     libbfio_handle_t *file_io_handle,
936
     libcerror_error_t **error )
937
2.46k
{
938
2.46k
  libfsfat_boot_record_t *boot_record = NULL;
939
2.46k
  static char *function               = "libfsfat_internal_volume_open_read";
940
941
2.46k
  if( internal_volume == NULL )
942
0
  {
943
0
    libcerror_error_set(
944
0
     error,
945
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
946
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
947
0
     "%s: invalid internal volume.",
948
0
     function );
949
950
0
    return( -1 );
951
0
  }
952
2.46k
  if( internal_volume->io_handle == NULL )
953
0
  {
954
0
    libcerror_error_set(
955
0
     error,
956
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
957
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
958
0
     "%s: invalid internal volume - missing IO handle.",
959
0
     function );
960
961
0
    return( -1 );
962
0
  }
963
2.46k
  if( internal_volume->file_system != NULL )
964
0
  {
965
0
    libcerror_error_set(
966
0
     error,
967
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
968
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
969
0
     "%s: invalid volume - file system value already set.",
970
0
     function );
971
972
0
    return( -1 );
973
0
  }
974
2.46k
  if( libbfio_handle_get_size(
975
2.46k
       file_io_handle,
976
2.46k
       &( internal_volume->io_handle->volume_size ),
977
2.46k
       error ) != 1 )
978
0
  {
979
0
    libcerror_error_set(
980
0
     error,
981
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
982
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
983
0
     "%s: unable to retrieve file size.",
984
0
     function );
985
986
0
    goto on_error;
987
0
  }
988
#if defined( HAVE_DEBUG_OUTPUT )
989
  if( libcnotify_verbose != 0 )
990
  {
991
    libcnotify_printf(
992
     "%s: reading boot record.\n",
993
     function );
994
  }
995
#endif
996
2.46k
  if( libfsfat_boot_record_initialize(
997
2.46k
       &boot_record,
998
2.46k
       error ) != 1 )
999
0
  {
1000
0
    libcerror_error_set(
1001
0
     error,
1002
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1003
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1004
0
     "%s: unable to create boot record.",
1005
0
     function );
1006
1007
0
    goto on_error;
1008
0
  }
1009
2.46k
  if( libfsfat_boot_record_read_file_io_handle(
1010
2.46k
       boot_record,
1011
2.46k
       file_io_handle,
1012
2.46k
       0,
1013
2.46k
       error ) != 1 )
1014
366
  {
1015
366
    libcerror_error_set(
1016
366
     error,
1017
366
     LIBCERROR_ERROR_DOMAIN_IO,
1018
366
     LIBCERROR_IO_ERROR_READ_FAILED,
1019
366
     "%s: unable to read boot record.",
1020
366
     function );
1021
1022
366
    goto on_error;
1023
366
  }
1024
2.09k
  internal_volume->io_handle->file_system_format       = boot_record->file_system_format;
1025
2.09k
  internal_volume->io_handle->bytes_per_sector         = boot_record->bytes_per_sector;
1026
2.09k
  internal_volume->io_handle->cluster_block_size       = boot_record->cluster_block_size;
1027
2.09k
  internal_volume->io_handle->total_number_of_clusters = boot_record->total_number_of_clusters;
1028
2.09k
  internal_volume->io_handle->first_cluster_offset     = boot_record->first_cluster_offset;
1029
1030
2.09k
  if( boot_record->root_directory_size > 0 )
1031
332
  {
1032
332
    internal_volume->io_handle->root_directory_offset = boot_record->root_directory_offset;
1033
332
  }
1034
1.76k
  else
1035
1.76k
  {
1036
1.76k
    internal_volume->io_handle->root_directory_offset = boot_record->first_cluster_offset;
1037
1.76k
  }
1038
2.09k
  if( libfsfat_file_system_initialize(
1039
2.09k
       &( internal_volume->file_system ),
1040
2.09k
       internal_volume->io_handle,
1041
2.09k
       error ) != 1 )
1042
0
  {
1043
0
    libcerror_error_set(
1044
0
     error,
1045
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1046
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1047
0
     "%s: unable to create file system.",
1048
0
     function );
1049
1050
0
    goto on_error;
1051
0
  }
1052
#if defined( HAVE_DEBUG_OUTPUT )
1053
  if( libcnotify_verbose != 0 )
1054
  {
1055
    libcnotify_printf(
1056
     "%s: reading allocation table at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
1057
     function,
1058
     boot_record->allocation_table_offset,
1059
     boot_record->allocation_table_offset );
1060
  }
1061
#endif
1062
2.09k
  if( libfsfat_file_system_read_allocation_table(
1063
2.09k
       internal_volume->file_system,
1064
2.09k
       file_io_handle,
1065
2.09k
       boot_record->allocation_table_offset,
1066
2.09k
       boot_record->allocation_table_size,
1067
2.09k
       error ) != 1 )
1068
429
  {
1069
429
    libcerror_error_set(
1070
429
     error,
1071
429
     LIBCERROR_ERROR_DOMAIN_IO,
1072
429
     LIBCERROR_IO_ERROR_READ_FAILED,
1073
429
     "%s: unable to read allocation table.",
1074
429
     function );
1075
1076
429
    goto on_error;
1077
429
  }
1078
#if defined( HAVE_DEBUG_OUTPUT )
1079
  if( libcnotify_verbose != 0 )
1080
  {
1081
    libcnotify_printf(
1082
     "%s: reading root directory.\n",
1083
     function );
1084
  }
1085
#endif
1086
1.66k
  if( libfsfat_file_system_read_root_directory(
1087
1.66k
       internal_volume->file_system,
1088
1.66k
       file_io_handle,
1089
1.66k
       boot_record->root_directory_offset,
1090
1.66k
       boot_record->root_directory_size,
1091
1.66k
       boot_record->root_directory_cluster,
1092
1.66k
       error ) != 1 )
1093
1.35k
  {
1094
1.35k
    libcerror_error_set(
1095
1.35k
     error,
1096
1.35k
     LIBCERROR_ERROR_DOMAIN_IO,
1097
1.35k
     LIBCERROR_IO_ERROR_READ_FAILED,
1098
1.35k
     "%s: unable to read root directory.",
1099
1.35k
     function );
1100
1101
1.35k
    goto on_error;
1102
1.35k
  }
1103
308
  if( libfsfat_boot_record_free(
1104
308
       &boot_record,
1105
308
       error ) != 1 )
1106
0
  {
1107
0
    libcerror_error_set(
1108
0
     error,
1109
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1110
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1111
0
     "%s: unable to free boot record.",
1112
0
     function );
1113
1114
0
    goto on_error;
1115
0
  }
1116
308
  return( 1 );
1117
1118
2.15k
on_error:
1119
2.15k
  if( internal_volume->file_system != NULL )
1120
1.78k
  {
1121
1.78k
    libfsfat_file_system_free(
1122
1.78k
     &( internal_volume->file_system ),
1123
1.78k
     NULL );
1124
1.78k
  }
1125
2.15k
  if( boot_record != NULL )
1126
2.15k
  {
1127
2.15k
    libfsfat_boot_record_free(
1128
2.15k
     &boot_record,
1129
2.15k
     NULL );
1130
2.15k
  }
1131
2.15k
  return( -1 );
1132
308
}
1133
1134
/* Retrieves the file system format
1135
 * Returns 1 if successful or -1 on error
1136
 */
1137
int libfsfat_volume_get_file_system_format(
1138
     libfsfat_volume_t *volume,
1139
     uint8_t *file_system_format,
1140
     libcerror_error_t **error )
1141
0
{
1142
0
  libfsfat_internal_volume_t *internal_volume = NULL;
1143
0
  static char *function                       = "libfsfat_volume_get_file_system_format";
1144
1145
0
  if( volume == NULL )
1146
0
  {
1147
0
    libcerror_error_set(
1148
0
     error,
1149
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1150
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1151
0
     "%s: invalid volume.",
1152
0
     function );
1153
1154
0
    return( -1 );
1155
0
  }
1156
0
  internal_volume = (libfsfat_internal_volume_t *) volume;
1157
1158
0
  if( internal_volume->io_handle == NULL )
1159
0
  {
1160
0
    libcerror_error_set(
1161
0
     error,
1162
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1163
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1164
0
     "%s: invalid volume - missing IO handle.",
1165
0
     function );
1166
1167
0
    return( -1 );
1168
0
  }
1169
0
  if( file_system_format == NULL )
1170
0
  {
1171
0
    libcerror_error_set(
1172
0
     error,
1173
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1174
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1175
0
     "%s: invalid file system format.",
1176
0
     function );
1177
1178
0
    return( -1 );
1179
0
  }
1180
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1181
0
  if( libcthreads_read_write_lock_grab_for_read(
1182
0
       internal_volume->read_write_lock,
1183
0
       error ) != 1 )
1184
0
  {
1185
0
    libcerror_error_set(
1186
0
     error,
1187
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1188
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1189
0
     "%s: unable to grab read/write lock for reading.",
1190
0
     function );
1191
1192
0
    return( -1 );
1193
0
  }
1194
0
#endif
1195
0
  *file_system_format = internal_volume->io_handle->file_system_format;
1196
1197
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1198
0
  if( libcthreads_read_write_lock_release_for_read(
1199
0
       internal_volume->read_write_lock,
1200
0
       error ) != 1 )
1201
0
  {
1202
0
    libcerror_error_set(
1203
0
     error,
1204
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1205
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1206
0
     "%s: unable to release read/write lock for reading.",
1207
0
     function );
1208
1209
0
    return( -1 );
1210
0
  }
1211
0
#endif
1212
0
  return( 1 );
1213
0
}
1214
1215
/* Retrieves the size of the UTF-8 encoded label
1216
 * The returned size includes the end of string character
1217
 * Returns 1 if successful or -1 on error
1218
 */
1219
int libfsfat_volume_get_utf8_label_size(
1220
     libfsfat_volume_t *volume,
1221
     size_t *utf8_string_size,
1222
     libcerror_error_t **error )
1223
0
{
1224
0
  libfsfat_internal_volume_t *internal_volume = NULL;
1225
0
  static char *function                       = "libfsfat_volume_get_utf8_label_size";
1226
0
  int result                                  = 1;
1227
1228
0
  if( volume == NULL )
1229
0
  {
1230
0
    libcerror_error_set(
1231
0
     error,
1232
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1233
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1234
0
     "%s: invalid volume.",
1235
0
     function );
1236
1237
0
    return( -1 );
1238
0
  }
1239
0
  internal_volume = (libfsfat_internal_volume_t *) volume;
1240
1241
0
  if( internal_volume->file_system == NULL )
1242
0
  {
1243
0
    libcerror_error_set(
1244
0
     error,
1245
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1246
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1247
0
     "%s: invalid internal volume - missing file system.",
1248
0
     function );
1249
1250
0
    return( -1 );
1251
0
  }
1252
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1253
0
  if( libcthreads_read_write_lock_grab_for_read(
1254
0
       internal_volume->read_write_lock,
1255
0
       error ) != 1 )
1256
0
  {
1257
0
    libcerror_error_set(
1258
0
     error,
1259
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1260
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1261
0
     "%s: unable to grab read/write lock for reading.",
1262
0
     function );
1263
1264
0
    return( -1 );
1265
0
  }
1266
0
#endif
1267
0
  if( libfsfat_file_system_get_utf8_volume_label_size(
1268
0
       internal_volume->file_system,
1269
0
       utf8_string_size,
1270
0
       error ) != 1 )
1271
0
  {
1272
0
    libcerror_error_set(
1273
0
     error,
1274
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1275
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1276
0
     "%s: unable to retrieve size of UTF-8 volume label.",
1277
0
     function );
1278
1279
0
    result = -1;
1280
0
  }
1281
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1282
0
  if( libcthreads_read_write_lock_release_for_read(
1283
0
       internal_volume->read_write_lock,
1284
0
       error ) != 1 )
1285
0
  {
1286
0
    libcerror_error_set(
1287
0
     error,
1288
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1289
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1290
0
     "%s: unable to release read/write lock for reading.",
1291
0
     function );
1292
1293
0
    return( -1 );
1294
0
  }
1295
0
#endif
1296
0
  return( result );
1297
0
}
1298
1299
/* Retrieves the UTF-8 encoded label
1300
 * The size should include the end of string character
1301
 * Returns 1 if successful or -1 on error
1302
 */
1303
int libfsfat_volume_get_utf8_label(
1304
     libfsfat_volume_t *volume,
1305
     uint8_t *utf8_string,
1306
     size_t utf8_string_size,
1307
     libcerror_error_t **error )
1308
0
{
1309
0
  libfsfat_internal_volume_t *internal_volume = NULL;
1310
0
  static char *function                       = "libfsfat_volume_get_utf8_label";
1311
0
  int result                                  = 1;
1312
1313
0
  if( volume == NULL )
1314
0
  {
1315
0
    libcerror_error_set(
1316
0
     error,
1317
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1318
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1319
0
     "%s: invalid volume.",
1320
0
     function );
1321
1322
0
    return( -1 );
1323
0
  }
1324
0
  internal_volume = (libfsfat_internal_volume_t *) volume;
1325
1326
0
  if( internal_volume->file_system == NULL )
1327
0
  {
1328
0
    libcerror_error_set(
1329
0
     error,
1330
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1331
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1332
0
     "%s: invalid internal volume - missing file system.",
1333
0
     function );
1334
1335
0
    return( -1 );
1336
0
  }
1337
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1338
0
  if( libcthreads_read_write_lock_grab_for_read(
1339
0
       internal_volume->read_write_lock,
1340
0
       error ) != 1 )
1341
0
  {
1342
0
    libcerror_error_set(
1343
0
     error,
1344
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1345
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1346
0
     "%s: unable to grab read/write lock for reading.",
1347
0
     function );
1348
1349
0
    return( -1 );
1350
0
  }
1351
0
#endif
1352
0
  if( libfsfat_file_system_get_utf8_volume_label(
1353
0
       internal_volume->file_system,
1354
0
       utf8_string,
1355
0
       utf8_string_size,
1356
0
       error ) != 1 )
1357
0
  {
1358
0
    libcerror_error_set(
1359
0
     error,
1360
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1361
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1362
0
     "%s: unable to retrieve UTF-8 volume label.",
1363
0
     function );
1364
1365
0
    result = -1;
1366
0
  }
1367
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1368
0
  if( libcthreads_read_write_lock_release_for_read(
1369
0
       internal_volume->read_write_lock,
1370
0
       error ) != 1 )
1371
0
  {
1372
0
    libcerror_error_set(
1373
0
     error,
1374
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1375
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1376
0
     "%s: unable to release read/write lock for reading.",
1377
0
     function );
1378
1379
0
    return( -1 );
1380
0
  }
1381
0
#endif
1382
0
  return( result );
1383
0
}
1384
1385
/* Retrieves the size of the UTF-16 encoded label
1386
 * The returned size includes the end of string character
1387
 * Returns 1 if successful or -1 on error
1388
 */
1389
int libfsfat_volume_get_utf16_label_size(
1390
     libfsfat_volume_t *volume,
1391
     size_t *utf16_string_size,
1392
     libcerror_error_t **error )
1393
0
{
1394
0
  libfsfat_internal_volume_t *internal_volume = NULL;
1395
0
  static char *function                       = "libfsfat_volume_get_utf16_label_size";
1396
0
  int result                                  = 1;
1397
1398
0
  if( volume == 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 volume.",
1405
0
     function );
1406
1407
0
    return( -1 );
1408
0
  }
1409
0
  internal_volume = (libfsfat_internal_volume_t *) volume;
1410
1411
0
  if( internal_volume->file_system == NULL )
1412
0
  {
1413
0
    libcerror_error_set(
1414
0
     error,
1415
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1416
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1417
0
     "%s: invalid internal volume - missing file system.",
1418
0
     function );
1419
1420
0
    return( -1 );
1421
0
  }
1422
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1423
0
  if( libcthreads_read_write_lock_grab_for_read(
1424
0
       internal_volume->read_write_lock,
1425
0
       error ) != 1 )
1426
0
  {
1427
0
    libcerror_error_set(
1428
0
     error,
1429
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1430
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1431
0
     "%s: unable to grab read/write lock for reading.",
1432
0
     function );
1433
1434
0
    return( -1 );
1435
0
  }
1436
0
#endif
1437
0
  if( libfsfat_file_system_get_utf16_volume_label_size(
1438
0
       internal_volume->file_system,
1439
0
       utf16_string_size,
1440
0
       error ) != 1 )
1441
0
  {
1442
0
    libcerror_error_set(
1443
0
     error,
1444
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1445
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1446
0
     "%s: unable to retrieve size of UTF-16 volume label.",
1447
0
     function );
1448
1449
0
    result = -1;
1450
0
  }
1451
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1452
0
  if( libcthreads_read_write_lock_release_for_read(
1453
0
       internal_volume->read_write_lock,
1454
0
       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 release read/write lock for reading.",
1461
0
     function );
1462
1463
0
    return( -1 );
1464
0
  }
1465
0
#endif
1466
0
  return( result );
1467
0
}
1468
1469
/* Retrieves the UTF-16 encoded label
1470
 * The size should include the end of string character
1471
 * Returns 1 if successful or -1 on error
1472
 */
1473
int libfsfat_volume_get_utf16_label(
1474
     libfsfat_volume_t *volume,
1475
     uint16_t *utf16_string,
1476
     size_t utf16_string_size,
1477
     libcerror_error_t **error )
1478
0
{
1479
0
  libfsfat_internal_volume_t *internal_volume = NULL;
1480
0
  static char *function                       = "libfsfat_volume_get_utf16_label";
1481
0
  int result                                  = 1;
1482
1483
0
  if( volume == NULL )
1484
0
  {
1485
0
    libcerror_error_set(
1486
0
     error,
1487
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1488
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1489
0
     "%s: invalid volume.",
1490
0
     function );
1491
1492
0
    return( -1 );
1493
0
  }
1494
0
  internal_volume = (libfsfat_internal_volume_t *) volume;
1495
1496
0
  if( internal_volume->file_system == NULL )
1497
0
  {
1498
0
    libcerror_error_set(
1499
0
     error,
1500
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1501
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1502
0
     "%s: invalid internal volume - missing file system.",
1503
0
     function );
1504
1505
0
    return( -1 );
1506
0
  }
1507
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1508
0
  if( libcthreads_read_write_lock_grab_for_read(
1509
0
       internal_volume->read_write_lock,
1510
0
       error ) != 1 )
1511
0
  {
1512
0
    libcerror_error_set(
1513
0
     error,
1514
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1515
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1516
0
     "%s: unable to grab read/write lock for reading.",
1517
0
     function );
1518
1519
0
    return( -1 );
1520
0
  }
1521
0
#endif
1522
0
  if( libfsfat_file_system_get_utf16_volume_label(
1523
0
       internal_volume->file_system,
1524
0
       utf16_string,
1525
0
       utf16_string_size,
1526
0
       error ) != 1 )
1527
0
  {
1528
0
    libcerror_error_set(
1529
0
     error,
1530
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1531
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1532
0
     "%s: unable to retrieve UTF-16 volume label.",
1533
0
     function );
1534
1535
0
    result = -1;
1536
0
  }
1537
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1538
0
  if( libcthreads_read_write_lock_release_for_read(
1539
0
       internal_volume->read_write_lock,
1540
0
       error ) != 1 )
1541
0
  {
1542
0
    libcerror_error_set(
1543
0
     error,
1544
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1545
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1546
0
     "%s: unable to release read/write lock for reading.",
1547
0
     function );
1548
1549
0
    return( -1 );
1550
0
  }
1551
0
#endif
1552
0
  return( result );
1553
0
}
1554
1555
/* Retrieves the root directory file entry
1556
 * Returns 1 if successful or -1 on error
1557
 */
1558
int libfsfat_volume_get_root_directory(
1559
     libfsfat_volume_t *volume,
1560
     libfsfat_file_entry_t **file_entry,
1561
     libcerror_error_t **error )
1562
229
{
1563
229
  libfsfat_internal_volume_t *internal_volume = NULL;
1564
229
  static char *function                       = "libfsfat_volume_get_root_directory";
1565
229
  int result                                  = 1;
1566
1567
229
  if( volume == NULL )
1568
0
  {
1569
0
    libcerror_error_set(
1570
0
     error,
1571
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1572
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1573
0
     "%s: invalid volume.",
1574
0
     function );
1575
1576
0
    return( -1 );
1577
0
  }
1578
229
  internal_volume = (libfsfat_internal_volume_t *) volume;
1579
1580
229
  if( internal_volume->file_system == NULL )
1581
0
  {
1582
0
    libcerror_error_set(
1583
0
     error,
1584
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1585
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1586
0
     "%s: invalid internal volume - missing file system.",
1587
0
     function );
1588
1589
0
    return( -1 );
1590
0
  }
1591
229
  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
229
  if( *file_entry != NULL )
1603
0
  {
1604
0
    libcerror_error_set(
1605
0
     error,
1606
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1607
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1608
0
     "%s: invalid file entry value already set.",
1609
0
     function );
1610
1611
0
    return( -1 );
1612
0
  }
1613
229
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1614
229
  if( libcthreads_read_write_lock_grab_for_write(
1615
229
       internal_volume->read_write_lock,
1616
229
       error ) != 1 )
1617
0
  {
1618
0
    libcerror_error_set(
1619
0
     error,
1620
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1621
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1622
0
     "%s: unable to grab read/write lock for writing.",
1623
0
     function );
1624
1625
0
    return( -1 );
1626
0
  }
1627
229
#endif
1628
229
  if( libfsfat_file_system_get_root_directory(
1629
229
       internal_volume->file_system,
1630
229
       internal_volume->file_io_handle,
1631
229
       file_entry,
1632
229
       error ) != 1 )
1633
0
  {
1634
0
    libcerror_error_set(
1635
0
     error,
1636
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1637
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1638
0
     "%s: unable to retrieve root directory.",
1639
0
     function );
1640
1641
0
    result = -1;
1642
0
  }
1643
229
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1644
229
  if( libcthreads_read_write_lock_release_for_write(
1645
229
       internal_volume->read_write_lock,
1646
229
       error ) != 1 )
1647
0
  {
1648
0
    libcerror_error_set(
1649
0
     error,
1650
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1651
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1652
0
     "%s: unable to release read/write lock for writing.",
1653
0
     function );
1654
1655
0
    libfsfat_file_entry_free(
1656
0
     file_entry,
1657
0
     NULL );
1658
1659
0
    return( -1 );
1660
0
  }
1661
229
#endif
1662
229
  return( result );
1663
229
}
1664
1665
/* Retrieves the file entry of a specific identifier
1666
 * Returns 1 if successful or -1 on error
1667
 */
1668
int libfsfat_volume_get_file_entry_by_identifier(
1669
     libfsfat_volume_t *volume,
1670
     uint64_t identifier,
1671
     libfsfat_file_entry_t **file_entry,
1672
     libcerror_error_t **error )
1673
0
{
1674
0
  libfsfat_internal_volume_t *internal_volume = NULL;
1675
0
  static char *function                       = "libfsfat_volume_get_file_entry_by_identifier";
1676
0
  int result                                  = 1;
1677
1678
0
  if( volume == NULL )
1679
0
  {
1680
0
    libcerror_error_set(
1681
0
     error,
1682
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1683
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1684
0
     "%s: invalid volume.",
1685
0
     function );
1686
1687
0
    return( -1 );
1688
0
  }
1689
0
  internal_volume = (libfsfat_internal_volume_t *) volume;
1690
1691
0
  if( file_entry == NULL )
1692
0
  {
1693
0
    libcerror_error_set(
1694
0
     error,
1695
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1696
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1697
0
     "%s: invalid file entry.",
1698
0
     function );
1699
1700
0
    return( -1 );
1701
0
  }
1702
0
  if( *file_entry != NULL )
1703
0
  {
1704
0
    libcerror_error_set(
1705
0
     error,
1706
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1707
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1708
0
     "%s: invalid file entry value already set.",
1709
0
     function );
1710
1711
0
    return( -1 );
1712
0
  }
1713
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1714
0
  if( libcthreads_read_write_lock_grab_for_write(
1715
0
       internal_volume->read_write_lock,
1716
0
       error ) != 1 )
1717
0
  {
1718
0
    libcerror_error_set(
1719
0
     error,
1720
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1721
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1722
0
     "%s: unable to grab read/write lock for writing.",
1723
0
     function );
1724
1725
0
    return( -1 );
1726
0
  }
1727
0
#endif
1728
0
  if( libfsfat_file_system_get_file_entry_by_identifier(
1729
0
       internal_volume->file_system,
1730
0
       internal_volume->file_io_handle,
1731
0
       identifier,
1732
0
       file_entry,
1733
0
       error ) != 1 )
1734
0
  {
1735
0
    libcerror_error_set(
1736
0
     error,
1737
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1738
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1739
0
     "%s: unable to retrieve identifier: %" PRIu64 ".",
1740
0
     function,
1741
0
     identifier );
1742
1743
0
    result = -1;
1744
0
  }
1745
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1746
0
  if( libcthreads_read_write_lock_release_for_write(
1747
0
       internal_volume->read_write_lock,
1748
0
       error ) != 1 )
1749
0
  {
1750
0
    libcerror_error_set(
1751
0
     error,
1752
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1753
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1754
0
     "%s: unable to release read/write lock for writing.",
1755
0
     function );
1756
1757
0
    libfsfat_file_entry_free(
1758
0
     file_entry,
1759
0
     NULL );
1760
1761
0
    return( -1 );
1762
0
  }
1763
0
#endif
1764
0
  return( result );
1765
0
}
1766
1767
/* Retrieves the file entry for an UTF-8 encoded path
1768
 * Returns 1 if successful, 0 if no such file entry or -1 on error
1769
 */
1770
int libfsfat_volume_get_file_entry_by_utf8_path(
1771
     libfsfat_volume_t *volume,
1772
     const uint8_t *utf8_string,
1773
     size_t utf8_string_length,
1774
     libfsfat_file_entry_t **file_entry,
1775
     libcerror_error_t **error )
1776
0
{
1777
0
  libfsfat_internal_volume_t *internal_volume = NULL;
1778
0
  static char *function                       = "libfsfat_volume_get_file_entry_by_utf8_path";
1779
0
  int result                                  = 0;
1780
1781
0
  if( volume == NULL )
1782
0
  {
1783
0
    libcerror_error_set(
1784
0
     error,
1785
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1786
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1787
0
     "%s: invalid volume.",
1788
0
     function );
1789
1790
0
    return( -1 );
1791
0
  }
1792
0
  internal_volume = (libfsfat_internal_volume_t *) volume;
1793
1794
0
  if( file_entry == NULL )
1795
0
  {
1796
0
    libcerror_error_set(
1797
0
     error,
1798
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1799
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1800
0
     "%s: invalid file entry.",
1801
0
     function );
1802
1803
0
    return( -1 );
1804
0
  }
1805
0
  if( *file_entry != NULL )
1806
0
  {
1807
0
    libcerror_error_set(
1808
0
     error,
1809
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1810
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1811
0
     "%s: invalid file entry value already set.",
1812
0
     function );
1813
1814
0
    return( -1 );
1815
0
  }
1816
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1817
0
  if( libcthreads_read_write_lock_grab_for_write(
1818
0
       internal_volume->read_write_lock,
1819
0
       error ) != 1 )
1820
0
  {
1821
0
    libcerror_error_set(
1822
0
     error,
1823
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1824
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1825
0
     "%s: unable to grab read/write lock for writing.",
1826
0
     function );
1827
1828
0
    return( -1 );
1829
0
  }
1830
0
#endif
1831
0
  result = libfsfat_file_system_get_file_entry_by_utf8_path(
1832
0
            internal_volume->file_system,
1833
0
            internal_volume->file_io_handle,
1834
0
            utf8_string,
1835
0
            utf8_string_length,
1836
0
            file_entry,
1837
0
            error );
1838
1839
0
  if( result == -1 )
1840
0
  {
1841
0
    libcerror_error_set(
1842
0
     error,
1843
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1844
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1845
0
     "%s: unable to retrieve file entry by UTF-8 encoded path.",
1846
0
     function );
1847
1848
0
    result = -1;
1849
0
  }
1850
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1851
0
  if( libcthreads_read_write_lock_release_for_write(
1852
0
       internal_volume->read_write_lock,
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_SET_FAILED,
1859
0
     "%s: unable to release read/write lock for writing.",
1860
0
     function );
1861
1862
0
    libfsfat_file_entry_free(
1863
0
     file_entry,
1864
0
     NULL );
1865
1866
0
    return( -1 );
1867
0
  }
1868
0
#endif
1869
0
  return( result );
1870
0
}
1871
1872
/* Retrieves the file entry for an UTF-16 encoded path
1873
 * Returns 1 if successful, 0 if no such file entry or -1 on error
1874
 */
1875
int libfsfat_volume_get_file_entry_by_utf16_path(
1876
     libfsfat_volume_t *volume,
1877
     const uint16_t *utf16_string,
1878
     size_t utf16_string_length,
1879
     libfsfat_file_entry_t **file_entry,
1880
     libcerror_error_t **error )
1881
0
{
1882
0
  libfsfat_internal_volume_t *internal_volume = NULL;
1883
0
  static char *function                       = "libfsfat_volume_get_file_entry_by_utf16_path";
1884
0
  int result                                  = 0;
1885
1886
0
  if( volume == NULL )
1887
0
  {
1888
0
    libcerror_error_set(
1889
0
     error,
1890
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1891
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1892
0
     "%s: invalid volume.",
1893
0
     function );
1894
1895
0
    return( -1 );
1896
0
  }
1897
0
  internal_volume = (libfsfat_internal_volume_t *) volume;
1898
1899
0
  if( file_entry == NULL )
1900
0
  {
1901
0
    libcerror_error_set(
1902
0
     error,
1903
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1904
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1905
0
     "%s: invalid file entry.",
1906
0
     function );
1907
1908
0
    return( -1 );
1909
0
  }
1910
0
  if( *file_entry != NULL )
1911
0
  {
1912
0
    libcerror_error_set(
1913
0
     error,
1914
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1915
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1916
0
     "%s: invalid file entry value already set.",
1917
0
     function );
1918
1919
0
    return( -1 );
1920
0
  }
1921
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1922
0
  if( libcthreads_read_write_lock_grab_for_write(
1923
0
       internal_volume->read_write_lock,
1924
0
       error ) != 1 )
1925
0
  {
1926
0
    libcerror_error_set(
1927
0
     error,
1928
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1929
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1930
0
     "%s: unable to grab read/write lock for writing.",
1931
0
     function );
1932
1933
0
    return( -1 );
1934
0
  }
1935
0
#endif
1936
0
  result = libfsfat_file_system_get_file_entry_by_utf16_path(
1937
0
            internal_volume->file_system,
1938
0
            internal_volume->file_io_handle,
1939
0
            utf16_string,
1940
0
            utf16_string_length,
1941
0
            file_entry,
1942
0
            error );
1943
1944
0
  if( result == -1 )
1945
0
  {
1946
0
    libcerror_error_set(
1947
0
     error,
1948
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1949
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1950
0
     "%s: unable to retrieve file entry by UTF-16 encoded path.",
1951
0
     function );
1952
1953
0
    result = -1;
1954
0
  }
1955
0
#if defined( HAVE_LIBFSFAT_MULTI_THREAD_SUPPORT )
1956
0
  if( libcthreads_read_write_lock_release_for_write(
1957
0
       internal_volume->read_write_lock,
1958
0
       error ) != 1 )
1959
0
  {
1960
0
    libcerror_error_set(
1961
0
     error,
1962
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1963
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1964
0
     "%s: unable to release read/write lock for writing.",
1965
0
     function );
1966
1967
0
    libfsfat_file_entry_free(
1968
0
     file_entry,
1969
0
     NULL );
1970
1971
0
    return( -1 );
1972
0
  }
1973
0
#endif
1974
0
  return( result );
1975
0
}
1976