Coverage Report

Created: 2026-08-31 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfshfs/libfshfs/libfshfs_volume.c
Line
Count
Source
1
/*
2
 * Volume functions
3
 *
4
 * Copyright (C) 2009-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <narrow_string.h>
25
#include <types.h>
26
#include <wide_string.h>
27
28
#include "libfshfs_debug.h"
29
#include "libfshfs_definitions.h"
30
#include "libfshfs_directory_entry.h"
31
#include "libfshfs_file_entry.h"
32
#include "libfshfs_fork_descriptor.h"
33
#include "libfshfs_io_handle.h"
34
#include "libfshfs_libcdata.h"
35
#include "libfshfs_libcerror.h"
36
#include "libfshfs_libcnotify.h"
37
#include "libfshfs_libcthreads.h"
38
#include "libfshfs_master_directory_block.h"
39
#include "libfshfs_thread_record.h"
40
#include "libfshfs_volume.h"
41
#include "libfshfs_volume_header.h"
42
43
/* Creates a volume
44
 * Make sure the value volume is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libfshfs_volume_initialize(
48
     libfshfs_volume_t **volume,
49
     libcerror_error_t **error )
50
5.31k
{
51
5.31k
  libfshfs_internal_volume_t *internal_volume = NULL;
52
5.31k
  static char *function                       = "libfshfs_volume_initialize";
53
54
5.31k
  if( volume == NULL )
55
0
  {
56
0
    libcerror_error_set(
57
0
     error,
58
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
59
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
60
0
     "%s: invalid volume.",
61
0
     function );
62
63
0
    return( -1 );
64
0
  }
65
5.31k
  if( *volume != NULL )
66
0
  {
67
0
    libcerror_error_set(
68
0
     error,
69
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
70
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
71
0
     "%s: invalid volume value already set.",
72
0
     function );
73
74
0
    return( -1 );
75
0
  }
76
5.31k
  internal_volume = memory_allocate_structure(
77
5.31k
                     libfshfs_internal_volume_t );
78
79
5.31k
  if( internal_volume == NULL )
80
0
  {
81
0
    libcerror_error_set(
82
0
     error,
83
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
84
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
85
0
     "%s: unable to create volume.",
86
0
     function );
87
88
0
    goto on_error;
89
0
  }
90
5.31k
  if( memory_set(
91
5.31k
       internal_volume,
92
5.31k
       0,
93
5.31k
       sizeof( libfshfs_internal_volume_t ) ) == NULL )
94
0
  {
95
0
    libcerror_error_set(
96
0
     error,
97
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
98
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
99
0
     "%s: unable to clear volume.",
100
0
     function );
101
102
0
    goto on_error;
103
0
  }
104
5.31k
  if( libfshfs_io_handle_initialize(
105
5.31k
       &( internal_volume->io_handle ),
106
5.31k
       error ) != 1 )
107
0
  {
108
0
    libcerror_error_set(
109
0
     error,
110
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
111
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
112
0
     "%s: unable to create IO handle.",
113
0
     function );
114
115
0
    goto on_error;
116
0
  }
117
5.31k
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
118
5.31k
  if( libcthreads_read_write_lock_initialize(
119
5.31k
       &( internal_volume->read_write_lock ),
120
5.31k
       error ) != 1 )
121
0
  {
122
0
    libcerror_error_set(
123
0
     error,
124
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
125
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
126
0
     "%s: unable to initialize read/write lock.",
127
0
     function );
128
129
0
    goto on_error;
130
0
  }
131
5.31k
#endif
132
5.31k
  *volume = (libfshfs_volume_t *) internal_volume;
133
134
5.31k
  return( 1 );
135
136
0
on_error:
137
0
  if( internal_volume != NULL )
138
0
  {
139
0
    memory_free(
140
0
     internal_volume );
141
0
  }
142
0
  return( -1 );
143
5.31k
}
144
145
/* Frees a volume
146
 * Returns 1 if successful or -1 on error
147
 */
148
int libfshfs_volume_free(
149
     libfshfs_volume_t **volume,
150
     libcerror_error_t **error )
151
5.31k
{
152
5.31k
  libfshfs_internal_volume_t *internal_volume = NULL;
153
5.31k
  static char *function                        = "libfshfs_volume_free";
154
5.31k
  int result                                   = 1;
155
156
5.31k
  if( volume == NULL )
157
0
  {
158
0
    libcerror_error_set(
159
0
     error,
160
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
161
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
162
0
     "%s: invalid volume.",
163
0
     function );
164
165
0
    return( -1 );
166
0
  }
167
5.31k
  if( *volume != NULL )
168
5.31k
  {
169
5.31k
    internal_volume = (libfshfs_internal_volume_t *) *volume;
170
171
5.31k
    if( internal_volume->file_io_handle != NULL )
172
0
    {
173
0
      if( libfshfs_volume_close(
174
0
           *volume,
175
0
           error ) != 0 )
176
0
      {
177
0
        libcerror_error_set(
178
0
         error,
179
0
         LIBCERROR_ERROR_DOMAIN_IO,
180
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
181
0
         "%s: unable to close volume.",
182
0
         function );
183
184
0
        result = -1;
185
0
      }
186
0
    }
187
5.31k
    *volume = NULL;
188
189
5.31k
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
190
5.31k
    if( libcthreads_read_write_lock_free(
191
5.31k
         &( internal_volume->read_write_lock ),
192
5.31k
         error ) != 1 )
193
0
    {
194
0
      libcerror_error_set(
195
0
       error,
196
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
197
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
198
0
       "%s: unable to free read/write lock.",
199
0
       function );
200
201
0
      result = -1;
202
0
    }
203
5.31k
#endif
204
5.31k
    if( libfshfs_io_handle_free(
205
5.31k
         &( internal_volume->io_handle ),
206
5.31k
         error ) != 1 )
207
0
    {
208
0
      libcerror_error_set(
209
0
       error,
210
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
211
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
212
0
       "%s: unable to free IO handle.",
213
0
       function );
214
215
0
      result = -1;
216
0
    }
217
5.31k
    memory_free(
218
5.31k
     internal_volume );
219
5.31k
  }
220
5.31k
  return( result );
221
5.31k
}
222
223
/* Signals the volume to abort its current activity
224
 * Returns 1 if successful or -1 on error
225
 */
226
int libfshfs_volume_signal_abort(
227
     libfshfs_volume_t *volume,
228
     libcerror_error_t **error )
229
0
{
230
0
  libfshfs_internal_volume_t *internal_volume = NULL;
231
0
  static char *function                       = "libfshfs_volume_signal_abort";
232
233
0
  if( volume == NULL )
234
0
  {
235
0
    libcerror_error_set(
236
0
     error,
237
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
238
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
239
0
     "%s: invalid volume.",
240
0
     function );
241
242
0
    return( -1 );
243
0
  }
244
0
  internal_volume = (libfshfs_internal_volume_t *) volume;
245
246
0
  if( internal_volume->io_handle == NULL )
247
0
  {
248
0
    libcerror_error_set(
249
0
     error,
250
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
251
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
252
0
     "%s: invalid volume - missing IO handle.",
253
0
     function );
254
255
0
    return( -1 );
256
0
  }
257
0
  internal_volume->io_handle->abort = 1;
258
259
0
  return( 1 );
260
0
}
261
262
/* Opens a volume
263
 * Returns 1 if successful or -1 on error
264
 */
265
int libfshfs_volume_open(
266
     libfshfs_volume_t *volume,
267
     const char *filename,
268
     int access_flags,
269
     libcerror_error_t **error )
270
0
{
271
0
  libbfio_handle_t *file_io_handle            = NULL;
272
0
  libfshfs_internal_volume_t *internal_volume = NULL;
273
0
  static char *function                       = "libfshfs_volume_open";
274
0
  size_t string_length                        = 0;
275
276
0
  if( volume == NULL )
277
0
  {
278
0
    libcerror_error_set(
279
0
     error,
280
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
281
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
282
0
     "%s: invalid volume.",
283
0
     function );
284
285
0
    return( -1 );
286
0
  }
287
0
  internal_volume = (libfshfs_internal_volume_t *) volume;
288
289
0
  if( filename == NULL )
290
0
  {
291
0
    libcerror_error_set(
292
0
     error,
293
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
294
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
295
0
     "%s: invalid filename.",
296
0
     function );
297
298
0
    return( -1 );
299
0
  }
300
0
  if( ( ( access_flags & LIBFSHFS_ACCESS_FLAG_READ ) == 0 )
301
0
   && ( ( access_flags & LIBFSHFS_ACCESS_FLAG_WRITE ) == 0 ) )
302
0
  {
303
0
    libcerror_error_set(
304
0
     error,
305
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
306
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
307
0
     "%s: unsupported access flags.",
308
0
     function );
309
310
0
    return( -1 );
311
0
  }
312
0
  if( ( access_flags & LIBFSHFS_ACCESS_FLAG_WRITE ) != 0 )
313
0
  {
314
0
    libcerror_error_set(
315
0
     error,
316
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
317
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
318
0
     "%s: write access currently not supported.",
319
0
     function );
320
321
0
    return( -1 );
322
0
  }
323
0
  if( libbfio_file_initialize(
324
0
       &file_io_handle,
325
0
       error ) != 1 )
326
0
  {
327
0
    libcerror_error_set(
328
0
     error,
329
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
330
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
331
0
     "%s: unable to create file IO handle.",
332
0
     function );
333
334
0
    goto on_error;
335
0
  }
336
#if defined( HAVE_DEBUG_OUTPUT )
337
  if( libbfio_handle_set_track_offsets_read(
338
       file_io_handle,
339
       1,
340
       error ) != 1 )
341
  {
342
                libcerror_error_set(
343
                 error,
344
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
345
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
346
                 "%s: unable to set track offsets read in file IO handle.",
347
                 function );
348
349
    goto on_error;
350
  }
351
#endif
352
0
  string_length = narrow_string_length(
353
0
                   filename );
354
355
0
  if( libbfio_file_set_name(
356
0
       file_io_handle,
357
0
       filename,
358
0
       string_length + 1,
359
0
       error ) != 1 )
360
0
  {
361
0
                libcerror_error_set(
362
0
                 error,
363
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
364
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
365
0
                 "%s: unable to set filename in file IO handle.",
366
0
                 function );
367
368
0
    goto on_error;
369
0
  }
370
0
  if( libfshfs_volume_open_file_io_handle(
371
0
       volume,
372
0
       file_io_handle,
373
0
       access_flags,
374
0
       error ) != 1 )
375
0
  {
376
0
    libcerror_error_set(
377
0
     error,
378
0
     LIBCERROR_ERROR_DOMAIN_IO,
379
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
380
0
     "%s: unable to open volume: %s.",
381
0
     function,
382
0
     filename );
383
384
0
    goto on_error;
385
0
  }
386
0
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
387
0
  if( libcthreads_read_write_lock_grab_for_write(
388
0
       internal_volume->read_write_lock,
389
0
       error ) != 1 )
390
0
  {
391
0
    libcerror_error_set(
392
0
     error,
393
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
394
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
395
0
     "%s: unable to grab read/write lock for writing.",
396
0
     function );
397
398
0
    return( -1 );
399
0
  }
400
0
#endif
401
0
  internal_volume->file_io_handle_created_in_library = 1;
402
403
0
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
404
0
  if( libcthreads_read_write_lock_release_for_write(
405
0
       internal_volume->read_write_lock,
406
0
       error ) != 1 )
407
0
  {
408
0
    libcerror_error_set(
409
0
     error,
410
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
411
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
412
0
     "%s: unable to release read/write lock for writing.",
413
0
     function );
414
415
0
    return( -1 );
416
0
  }
417
0
#endif
418
0
  return( 1 );
419
420
0
on_error:
421
0
  if( file_io_handle != NULL )
422
0
  {
423
0
    libbfio_handle_free(
424
0
     &file_io_handle,
425
0
     NULL );
426
0
  }
427
0
        return( -1 );
428
0
}
429
430
#if defined( HAVE_WIDE_CHARACTER_TYPE )
431
432
/* Opens a volume
433
 * Returns 1 if successful or -1 on error
434
 */
435
int libfshfs_volume_open_wide(
436
     libfshfs_volume_t *volume,
437
     const wchar_t *filename,
438
     int access_flags,
439
     libcerror_error_t **error )
440
{
441
  libbfio_handle_t *file_io_handle            = NULL;
442
  libfshfs_internal_volume_t *internal_volume = NULL;
443
  static char *function                       = "libfshfs_volume_open_wide";
444
  size_t string_length                        = 0;
445
446
  if( volume == NULL )
447
  {
448
    libcerror_error_set(
449
     error,
450
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
451
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
452
     "%s: invalid volume.",
453
     function );
454
455
    return( -1 );
456
  }
457
  internal_volume = (libfshfs_internal_volume_t *) volume;
458
459
  if( filename == NULL )
460
  {
461
    libcerror_error_set(
462
     error,
463
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
464
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
465
     "%s: invalid filename.",
466
     function );
467
468
    return( -1 );
469
  }
470
  if( ( ( access_flags & LIBFSHFS_ACCESS_FLAG_READ ) == 0 )
471
   && ( ( access_flags & LIBFSHFS_ACCESS_FLAG_WRITE ) == 0 ) )
472
  {
473
    libcerror_error_set(
474
     error,
475
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
476
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
477
     "%s: unsupported access flags.",
478
     function );
479
480
    return( -1 );
481
  }
482
  if( ( access_flags & LIBFSHFS_ACCESS_FLAG_WRITE ) != 0 )
483
  {
484
    libcerror_error_set(
485
     error,
486
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
487
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
488
     "%s: write access currently not supported.",
489
     function );
490
491
    return( -1 );
492
  }
493
  if( libbfio_file_initialize(
494
       &file_io_handle,
495
       error ) != 1 )
496
  {
497
    libcerror_error_set(
498
     error,
499
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
500
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
501
     "%s: unable to create file IO handle.",
502
     function );
503
504
    goto on_error;
505
  }
506
#if defined( HAVE_DEBUG_OUTPUT )
507
  if( libbfio_handle_set_track_offsets_read(
508
       file_io_handle,
509
       1,
510
       error ) != 1 )
511
  {
512
                libcerror_error_set(
513
                 error,
514
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
515
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
516
                 "%s: unable to set track offsets read in file IO handle.",
517
                 function );
518
519
    goto on_error;
520
  }
521
#endif
522
  string_length = wide_string_length(
523
                   filename );
524
525
  if( libbfio_file_set_name_wide(
526
       file_io_handle,
527
       filename,
528
       string_length + 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( libfshfs_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_LIBFSHFS_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
    return( -1 );
569
  }
570
#endif
571
  internal_volume->file_io_handle_created_in_library = 1;
572
573
#if defined( HAVE_LIBFSHFS_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
    return( -1 );
586
  }
587
#endif
588
  return( 1 );
589
590
on_error:
591
  if( file_io_handle != NULL )
592
  {
593
    libbfio_handle_free(
594
     &file_io_handle,
595
     NULL );
596
  }
597
        return( -1 );
598
}
599
600
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
601
602
/* Opens a volume using a Basic File IO (bfio) handle
603
 * Returns 1 if successful or -1 on error
604
 */
605
int libfshfs_volume_open_file_io_handle(
606
     libfshfs_volume_t *volume,
607
     libbfio_handle_t *file_io_handle,
608
     int access_flags,
609
     libcerror_error_t **error )
610
5.31k
{
611
5.31k
  libfshfs_internal_volume_t *internal_volume = NULL;
612
5.31k
  static char *function                       = "libfshfs_volume_open_file_io_handle";
613
5.31k
  uint8_t file_io_handle_opened_in_library    = 0;
614
5.31k
  int bfio_access_flags                       = 0;
615
5.31k
  int file_io_handle_is_open                  = 0;
616
617
5.31k
  if( volume == NULL )
618
0
  {
619
0
    libcerror_error_set(
620
0
     error,
621
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
622
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
623
0
     "%s: invalid volume.",
624
0
     function );
625
626
0
    return( -1 );
627
0
  }
628
5.31k
  internal_volume = (libfshfs_internal_volume_t *) volume;
629
630
5.31k
  if( internal_volume->file_io_handle != NULL )
631
0
  {
632
0
    libcerror_error_set(
633
0
     error,
634
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
635
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
636
0
     "%s: invalid volume - file IO handle already set.",
637
0
     function );
638
639
0
    return( -1 );
640
0
  }
641
5.31k
  if( file_io_handle == NULL )
642
0
  {
643
0
    libcerror_error_set(
644
0
     error,
645
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
646
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
647
0
     "%s: invalid file IO handle.",
648
0
     function );
649
650
0
    return( -1 );
651
0
  }
652
5.31k
  if( ( ( access_flags & LIBFSHFS_ACCESS_FLAG_READ ) == 0 )
653
0
   && ( ( access_flags & LIBFSHFS_ACCESS_FLAG_WRITE ) == 0 ) )
654
0
  {
655
0
    libcerror_error_set(
656
0
     error,
657
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
658
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
659
0
     "%s: unsupported access flags.",
660
0
     function );
661
662
0
    return( -1 );
663
0
  }
664
5.31k
  if( ( access_flags & LIBFSHFS_ACCESS_FLAG_WRITE ) != 0 )
665
0
  {
666
0
    libcerror_error_set(
667
0
     error,
668
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
669
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
670
0
     "%s: write access currently not supported.",
671
0
     function );
672
673
0
    return( -1 );
674
0
  }
675
5.31k
  if( ( access_flags & LIBFSHFS_ACCESS_FLAG_READ ) != 0 )
676
5.31k
  {
677
5.31k
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
678
5.31k
  }
679
5.31k
  file_io_handle_is_open = libbfio_handle_is_open(
680
5.31k
                            file_io_handle,
681
5.31k
                            error );
682
683
5.31k
  if( file_io_handle_is_open == -1 )
684
0
  {
685
0
    libcerror_error_set(
686
0
     error,
687
0
     LIBCERROR_ERROR_DOMAIN_IO,
688
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
689
0
     "%s: unable to open volume.",
690
0
     function );
691
692
0
    goto on_error;
693
0
  }
694
5.31k
  else if( file_io_handle_is_open == 0 )
695
5.31k
  {
696
5.31k
    if( libbfio_handle_open(
697
5.31k
         file_io_handle,
698
5.31k
         bfio_access_flags,
699
5.31k
         error ) != 1 )
700
0
    {
701
0
      libcerror_error_set(
702
0
       error,
703
0
       LIBCERROR_ERROR_DOMAIN_IO,
704
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
705
0
       "%s: unable to open file IO handle.",
706
0
       function );
707
708
0
      goto on_error;
709
0
    }
710
5.31k
    file_io_handle_opened_in_library = 1;
711
5.31k
  }
712
5.31k
  if( libfshfs_internal_volume_open_read(
713
5.31k
       internal_volume,
714
5.31k
       file_io_handle,
715
5.31k
       1024,
716
5.31k
       error ) != 1 )
717
2.60k
  {
718
2.60k
    libcerror_error_set(
719
2.60k
     error,
720
2.60k
     LIBCERROR_ERROR_DOMAIN_IO,
721
2.60k
     LIBCERROR_IO_ERROR_READ_FAILED,
722
2.60k
     "%s: unable to read from file IO handle.",
723
2.60k
     function );
724
725
2.60k
    goto on_error;
726
2.60k
  }
727
2.71k
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
728
2.71k
  if( libcthreads_read_write_lock_grab_for_write(
729
2.71k
       internal_volume->read_write_lock,
730
2.71k
       error ) != 1 )
731
0
  {
732
0
    libcerror_error_set(
733
0
     error,
734
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
735
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
736
0
     "%s: unable to grab read/write lock for writing.",
737
0
     function );
738
739
0
    return( -1 );
740
0
  }
741
2.71k
#endif
742
2.71k
  internal_volume->file_io_handle                   = file_io_handle;
743
2.71k
  internal_volume->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
744
745
2.71k
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
746
2.71k
  if( libcthreads_read_write_lock_release_for_write(
747
2.71k
       internal_volume->read_write_lock,
748
2.71k
       error ) != 1 )
749
0
  {
750
0
    libcerror_error_set(
751
0
     error,
752
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
753
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
754
0
     "%s: unable to release read/write lock for writing.",
755
0
     function );
756
757
0
    return( -1 );
758
0
  }
759
2.71k
#endif
760
2.71k
  return( 1 );
761
762
2.60k
on_error:
763
2.60k
  if( file_io_handle_opened_in_library != 0 )
764
2.60k
  {
765
2.60k
    libbfio_handle_close(
766
2.60k
     file_io_handle,
767
2.60k
     error );
768
2.60k
  }
769
2.60k
  return( -1 );
770
2.71k
}
771
772
/* Closes a volume
773
 * Returns 0 if successful or -1 on error
774
 */
775
int libfshfs_volume_close(
776
     libfshfs_volume_t *volume,
777
     libcerror_error_t **error )
778
2.71k
{
779
2.71k
  libfshfs_internal_volume_t *internal_volume = NULL;
780
2.71k
  static char *function                       = "libfshfs_volume_close";
781
2.71k
  int result                                  = 0;
782
783
2.71k
  if( volume == NULL )
784
0
  {
785
0
    libcerror_error_set(
786
0
     error,
787
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
788
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
789
0
     "%s: invalid volume.",
790
0
     function );
791
792
0
    return( -1 );
793
0
  }
794
2.71k
  internal_volume = (libfshfs_internal_volume_t *) volume;
795
796
2.71k
  if( internal_volume->file_io_handle == NULL )
797
0
  {
798
0
    libcerror_error_set(
799
0
     error,
800
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
801
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
802
0
     "%s: invalid volume - missing file IO handle.",
803
0
     function );
804
805
0
    return( -1 );
806
0
  }
807
2.71k
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
808
2.71k
  if( libcthreads_read_write_lock_grab_for_write(
809
2.71k
       internal_volume->read_write_lock,
810
2.71k
       error ) != 1 )
811
0
  {
812
0
    libcerror_error_set(
813
0
     error,
814
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
815
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
816
0
     "%s: unable to grab read/write lock for writing.",
817
0
     function );
818
819
0
    return( -1 );
820
0
  }
821
2.71k
#endif
822
#if defined( HAVE_DEBUG_OUTPUT )
823
  if( libcnotify_verbose != 0 )
824
  {
825
    if( internal_volume->file_io_handle_created_in_library != 0 )
826
    {
827
      if( libfshfs_debug_print_read_offsets(
828
           internal_volume->file_io_handle,
829
           error ) != 1 )
830
      {
831
        libcerror_error_set(
832
         error,
833
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
834
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
835
         "%s: unable to print the read offsets.",
836
         function );
837
838
        result = -1;
839
      }
840
    }
841
  }
842
#endif
843
2.71k
  if( internal_volume->file_io_handle_opened_in_library != 0 )
844
2.71k
  {
845
2.71k
    if( libbfio_handle_close(
846
2.71k
         internal_volume->file_io_handle,
847
2.71k
         error ) != 0 )
848
0
    {
849
0
      libcerror_error_set(
850
0
       error,
851
0
       LIBCERROR_ERROR_DOMAIN_IO,
852
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
853
0
       "%s: unable to close file IO handle.",
854
0
       function );
855
856
0
      result = -1;
857
0
    }
858
2.71k
    internal_volume->file_io_handle_opened_in_library = 0;
859
2.71k
  }
860
2.71k
  if( internal_volume->file_io_handle_created_in_library != 0 )
861
0
  {
862
0
    if( libbfio_handle_free(
863
0
         &( internal_volume->file_io_handle ),
864
0
         error ) != 1 )
865
0
    {
866
0
      libcerror_error_set(
867
0
       error,
868
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
869
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
870
0
       "%s: unable to free file IO handle.",
871
0
       function );
872
873
0
      result = -1;
874
0
    }
875
0
    internal_volume->file_io_handle_created_in_library = 0;
876
0
  }
877
2.71k
  internal_volume->file_io_handle = NULL;
878
879
2.71k
  if( libfshfs_io_handle_clear(
880
2.71k
       internal_volume->io_handle,
881
2.71k
       error ) != 1 )
882
0
  {
883
0
    libcerror_error_set(
884
0
     error,
885
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
886
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
887
0
     "%s: unable to clear IO handle.",
888
0
     function );
889
890
0
    result = -1;
891
0
  }
892
2.71k
  if( internal_volume->volume_header != NULL )
893
2.71k
  {
894
2.71k
    if( libfshfs_volume_header_free(
895
2.71k
         &( internal_volume->volume_header ),
896
2.71k
         error ) != 1 )
897
0
    {
898
0
      libcerror_error_set(
899
0
       error,
900
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
901
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
902
0
       "%s: unable to free volume header.",
903
0
       function );
904
905
0
      result = -1;
906
0
    }
907
2.71k
  }
908
2.71k
  if( internal_volume->master_directory_block != NULL )
909
0
  {
910
0
    if( libfshfs_master_directory_block_free(
911
0
         &( internal_volume->master_directory_block ),
912
0
         error ) != 1 )
913
0
    {
914
0
      libcerror_error_set(
915
0
       error,
916
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
917
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
918
0
       "%s: unable to free master directory block.",
919
0
       function );
920
921
0
      result = -1;
922
0
    }
923
0
  }
924
2.71k
  if( internal_volume->file_system != NULL )
925
2.71k
  {
926
2.71k
    if( libfshfs_file_system_free(
927
2.71k
         &( internal_volume->file_system ),
928
2.71k
         error ) != 1 )
929
0
    {
930
0
      libcerror_error_set(
931
0
       error,
932
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
933
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
934
0
       "%s: unable to free file system.",
935
0
       function );
936
937
0
      result = -1;
938
0
    }
939
2.71k
  }
940
2.71k
  if( internal_volume->root_directory_entry != NULL )
941
1.72k
  {
942
1.72k
    if( libfshfs_directory_entry_free(
943
1.72k
         &( internal_volume->root_directory_entry ),
944
1.72k
         error ) != 1 )
945
0
    {
946
0
      libcerror_error_set(
947
0
       error,
948
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
949
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
950
0
       "%s: unable to free root directory entry.",
951
0
       function );
952
953
0
      result = -1;
954
0
    }
955
1.72k
  }
956
2.71k
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
957
2.71k
  if( libcthreads_read_write_lock_release_for_write(
958
2.71k
       internal_volume->read_write_lock,
959
2.71k
       error ) != 1 )
960
0
  {
961
0
    libcerror_error_set(
962
0
     error,
963
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
964
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
965
0
     "%s: unable to release read/write lock for writing.",
966
0
     function );
967
968
0
    return( -1 );
969
0
  }
970
2.71k
#endif
971
2.71k
  return( result );
972
2.71k
}
973
974
/* Opens a volume for reading
975
 * Returns 1 if successful or -1 on error
976
 */
977
int libfshfs_internal_volume_open_read(
978
     libfshfs_internal_volume_t *internal_volume,
979
     libbfio_handle_t *file_io_handle,
980
     off64_t file_offset,
981
     libcerror_error_t **error )
982
5.31k
{
983
5.31k
  uint8_t signature[ 2 ];
984
985
5.31k
  libfshfs_fork_descriptor_t *attributes_file_fork_descriptor = NULL;
986
5.31k
  libfshfs_fork_descriptor_t *catalog_file_fork_descriptor    = NULL;
987
5.31k
  libfshfs_fork_descriptor_t *extents_file_fork_descriptor    = NULL;
988
5.31k
  static char *function                                       = "libfshfs_internal_volume_open_read";
989
5.31k
  ssize_t read_count                                          = 0;
990
5.31k
  uint8_t use_case_folding                                    = 0;
991
5.31k
  int result                                                  = 0;
992
993
5.31k
  if( internal_volume == NULL )
994
0
  {
995
0
    libcerror_error_set(
996
0
     error,
997
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
998
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
999
0
     "%s: invalid volume.",
1000
0
     function );
1001
1002
0
    return( -1 );
1003
0
  }
1004
5.31k
  if( internal_volume->io_handle == NULL )
1005
0
  {
1006
0
    libcerror_error_set(
1007
0
     error,
1008
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1009
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1010
0
     "%s: invalid volume - missing IO handle.",
1011
0
     function );
1012
1013
0
    return( -1 );
1014
0
  }
1015
5.31k
  if( internal_volume->volume_header != NULL )
1016
0
  {
1017
0
    libcerror_error_set(
1018
0
     error,
1019
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1020
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1021
0
     "%s: invalid volume - volume header value already set.",
1022
0
     function );
1023
1024
0
    return( -1 );
1025
0
  }
1026
5.31k
  if( internal_volume->master_directory_block != NULL )
1027
0
  {
1028
0
    libcerror_error_set(
1029
0
     error,
1030
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1031
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1032
0
     "%s: invalid volume - master directory block value already set.",
1033
0
     function );
1034
1035
0
    return( -1 );
1036
0
  }
1037
5.31k
  if( internal_volume->file_system != NULL )
1038
0
  {
1039
0
    libcerror_error_set(
1040
0
     error,
1041
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1042
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1043
0
     "%s: invalid volume - file system value already set.",
1044
0
     function );
1045
1046
0
    return( -1 );
1047
0
  }
1048
5.31k
  if( internal_volume->root_directory_entry != NULL )
1049
0
  {
1050
0
    libcerror_error_set(
1051
0
     error,
1052
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1053
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1054
0
     "%s: invalid volume - root directory entry value already set.",
1055
0
     function );
1056
1057
0
    return( -1 );
1058
0
  }
1059
5.31k
  read_count = libbfio_handle_read_buffer_at_offset(
1060
5.31k
                file_io_handle,
1061
5.31k
                signature,
1062
5.31k
                2,
1063
5.31k
                file_offset,
1064
5.31k
                error );
1065
1066
5.31k
  if( read_count != 2 )
1067
60
  {
1068
60
    libcerror_error_set(
1069
60
     error,
1070
60
     LIBCERROR_ERROR_DOMAIN_IO,
1071
60
     LIBCERROR_IO_ERROR_READ_FAILED,
1072
60
     "%s: unable to read signature at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1073
60
     function,
1074
60
     file_offset,
1075
60
     file_offset );
1076
1077
60
    goto on_error;
1078
60
  }
1079
5.25k
  if( memory_compare(
1080
5.25k
       "BD",
1081
5.25k
       signature,
1082
5.25k
       2 ) == 0 )
1083
176
  {
1084
#if defined( HAVE_DEBUG_OUTPUT )
1085
    if( libcnotify_verbose != 0 )
1086
    {
1087
      libcnotify_printf(
1088
       "Reading master directory block:\n" );
1089
    }
1090
#endif
1091
176
    if( libfshfs_master_directory_block_initialize(
1092
176
         &( internal_volume->master_directory_block ),
1093
176
         error ) != 1 )
1094
0
    {
1095
0
      libcerror_error_set(
1096
0
       error,
1097
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1098
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1099
0
       "%s: unable to create master directory block.",
1100
0
       function );
1101
1102
0
      goto on_error;
1103
0
    }
1104
176
    if( libfshfs_master_directory_block_read_file_io_handle(
1105
176
         internal_volume->master_directory_block,
1106
176
         file_io_handle,
1107
176
         file_offset,
1108
176
         error ) != 1 )
1109
173
    {
1110
173
      libcerror_error_set(
1111
173
       error,
1112
173
       LIBCERROR_ERROR_DOMAIN_IO,
1113
173
       LIBCERROR_IO_ERROR_READ_FAILED,
1114
173
       "%s: unable to read master directory block at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1115
173
       function,
1116
173
       file_offset,
1117
173
       file_offset );
1118
1119
173
      goto on_error;
1120
173
    }
1121
3
    internal_volume->io_handle->file_system_type = LIBFSHFS_FILE_SYSTEM_TYPE_HFS;
1122
3
    internal_volume->io_handle->block_size       = 512;
1123
1124
#if defined( HAVE_DEBUG_OUTPUT )
1125
    use_case_folding = 1;
1126
1127
    extents_file_fork_descriptor = internal_volume->master_directory_block->extents_file_fork_descriptor;
1128
    catalog_file_fork_descriptor = internal_volume->master_directory_block->catalog_file_fork_descriptor;
1129
#endif
1130
1131
/* TODO impement classic HFS support */
1132
3
    libcerror_error_set(
1133
3
     error,
1134
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1135
3
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1136
3
     "%s: classic HFS not supported.",
1137
3
     function );
1138
1139
3
    goto on_error;
1140
176
  }
1141
5.08k
  else
1142
5.08k
  {
1143
#if defined( HAVE_DEBUG_OUTPUT )
1144
    if( libcnotify_verbose != 0 )
1145
    {
1146
      libcnotify_printf(
1147
       "Reading volume header:\n" );
1148
    }
1149
#endif
1150
5.08k
    if( libfshfs_volume_header_initialize(
1151
5.08k
         &( internal_volume->volume_header ),
1152
5.08k
         error ) != 1 )
1153
0
    {
1154
0
      libcerror_error_set(
1155
0
       error,
1156
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1157
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1158
0
       "%s: unable to create volume header.",
1159
0
       function );
1160
1161
0
      goto on_error;
1162
0
    }
1163
5.08k
    if( libfshfs_volume_header_read_file_io_handle(
1164
5.08k
         internal_volume->volume_header,
1165
5.08k
         file_io_handle,
1166
5.08k
         file_offset,
1167
5.08k
         error ) != 1 )
1168
302
    {
1169
302
      libcerror_error_set(
1170
302
       error,
1171
302
       LIBCERROR_ERROR_DOMAIN_IO,
1172
302
       LIBCERROR_IO_ERROR_READ_FAILED,
1173
302
       "%s: unable to read volume header at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1174
302
       function,
1175
302
       file_offset,
1176
302
       file_offset );
1177
1178
302
      goto on_error;
1179
302
    }
1180
4.78k
    internal_volume->io_handle->file_system_type = internal_volume->volume_header->file_system_type;
1181
4.78k
    internal_volume->io_handle->block_size       = internal_volume->volume_header->allocation_block_size;
1182
1183
4.78k
    if( internal_volume->volume_header->file_system_type == LIBFSHFS_FILE_SYSTEM_TYPE_HFS_PLUS )
1184
3.91k
    {
1185
3.91k
      use_case_folding = 1;
1186
3.91k
    }
1187
4.78k
    extents_file_fork_descriptor    = internal_volume->volume_header->extents_file_fork_descriptor;
1188
4.78k
    catalog_file_fork_descriptor    = internal_volume->volume_header->catalog_file_fork_descriptor;
1189
4.78k
    attributes_file_fork_descriptor = internal_volume->volume_header->attributes_file_fork_descriptor;
1190
4.78k
  }
1191
4.78k
  if( libfshfs_file_system_initialize(
1192
4.78k
       &( internal_volume->file_system ),
1193
4.78k
       use_case_folding,
1194
4.78k
       error ) != 1 )
1195
0
  {
1196
0
    libcerror_error_set(
1197
0
     error,
1198
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1199
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1200
0
     "%s: unable to create file system.",
1201
0
     function );
1202
1203
0
    goto on_error;
1204
0
  }
1205
#if defined( HAVE_DEBUG_OUTPUT )
1206
  if( libcnotify_verbose != 0 )
1207
  {
1208
    libcnotify_printf(
1209
     "Reading extents B-tree file:\n" );
1210
  }
1211
#endif
1212
4.78k
  if( libfshfs_file_system_read_extents_file(
1213
4.78k
       internal_volume->file_system,
1214
4.78k
       internal_volume->io_handle,
1215
4.78k
       file_io_handle,
1216
4.78k
       extents_file_fork_descriptor,
1217
4.78k
       error ) != 1 )
1218
182
  {
1219
182
    libcerror_error_set(
1220
182
     error,
1221
182
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1222
182
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1223
182
     "%s: unable to read extents B-tree file.",
1224
182
     function );
1225
1226
182
    goto on_error;
1227
182
  }
1228
#if defined( HAVE_DEBUG_OUTPUT )
1229
  if( libcnotify_verbose != 0 )
1230
  {
1231
    libcnotify_printf(
1232
     "Reading catalog B-tree file:\n" );
1233
  }
1234
#endif
1235
4.59k
  if( libfshfs_file_system_read_catalog_file(
1236
4.59k
       internal_volume->file_system,
1237
4.59k
       internal_volume->io_handle,
1238
4.59k
       file_io_handle,
1239
4.59k
       catalog_file_fork_descriptor,
1240
4.59k
       error ) != 1 )
1241
750
  {
1242
750
    libcerror_error_set(
1243
750
     error,
1244
750
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1245
750
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1246
750
     "%s: unable to read catalog B-tree file.",
1247
750
     function );
1248
1249
750
    goto on_error;
1250
750
  }
1251
3.84k
  if( attributes_file_fork_descriptor != NULL )
1252
3.84k
  {
1253
#if defined( HAVE_DEBUG_OUTPUT )
1254
    if( libcnotify_verbose != 0 )
1255
    {
1256
      libcnotify_printf(
1257
       "Reading attributes B-tree file:\n" );
1258
    }
1259
#endif
1260
3.84k
    if( libfshfs_file_system_read_attributes_file(
1261
3.84k
         internal_volume->file_system,
1262
3.84k
         internal_volume->io_handle,
1263
3.84k
         file_io_handle,
1264
3.84k
         attributes_file_fork_descriptor,
1265
3.84k
         error ) != 1 )
1266
290
    {
1267
290
      libcerror_error_set(
1268
290
       error,
1269
290
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1270
290
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1271
290
       "%s: unable to read attributes B-tree file.",
1272
290
       function );
1273
1274
290
      goto on_error;
1275
290
    }
1276
3.84k
  }
1277
#if defined( HAVE_DEBUG_OUTPUT )
1278
  if( libcnotify_verbose != 0 )
1279
  {
1280
    libcnotify_printf(
1281
     "Reading root directory entry:\n" );
1282
  }
1283
#endif
1284
3.55k
  result = libfshfs_file_system_get_directory_entry_by_identifier(
1285
3.55k
            internal_volume->file_system,
1286
3.55k
            internal_volume->io_handle,
1287
3.55k
            file_io_handle,
1288
3.55k
            LIBFSHFS_ROOT_DIRECTORY_IDENTIFIER,
1289
3.55k
            &( internal_volume->root_directory_entry ),
1290
3.55k
            error );
1291
1292
3.55k
  if( result == -1 )
1293
843
  {
1294
843
    libcerror_error_set(
1295
843
     error,
1296
843
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1297
843
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1298
843
     "%s: unable to retrieve root directory entry from catalog B-tree file.",
1299
843
     function );
1300
1301
843
    goto on_error;
1302
843
  }
1303
2.71k
  return( 1 );
1304
1305
2.60k
on_error:
1306
2.60k
  if( internal_volume->root_directory_entry != NULL )
1307
0
  {
1308
0
    libfshfs_directory_entry_free(
1309
0
     &( internal_volume->root_directory_entry ),
1310
0
     NULL );
1311
0
  }
1312
2.60k
  if( internal_volume->file_system != NULL )
1313
2.06k
  {
1314
2.06k
    libfshfs_file_system_free(
1315
2.06k
     &( internal_volume->file_system ),
1316
2.06k
     NULL );
1317
2.06k
  }
1318
2.60k
  if( internal_volume->master_directory_block != NULL )
1319
176
  {
1320
176
    libfshfs_master_directory_block_free(
1321
176
     &( internal_volume->master_directory_block ),
1322
176
     NULL );
1323
176
  }
1324
2.60k
  if( internal_volume->volume_header != NULL )
1325
2.36k
  {
1326
2.36k
    libfshfs_volume_header_free(
1327
2.36k
     &( internal_volume->volume_header ),
1328
2.36k
     NULL );
1329
2.36k
  }
1330
2.60k
  return( -1 );
1331
3.55k
}
1332
1333
/* Retrieves the size of the UTF-8 encoded name
1334
 * The returned size includes the end of string character
1335
 * Returns 1 if successful or -1 on error
1336
 */
1337
int libfshfs_volume_get_utf8_name_size(
1338
     libfshfs_volume_t *volume,
1339
     size_t *utf8_string_size,
1340
     libcerror_error_t **error )
1341
357
{
1342
357
  libfshfs_internal_volume_t *internal_volume = NULL;
1343
357
  static char *function                       = "libfshfs_volume_get_utf8_name_size";
1344
357
  int result                                  = 1;
1345
1346
357
  if( volume == NULL )
1347
0
  {
1348
0
    libcerror_error_set(
1349
0
     error,
1350
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1351
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1352
0
     "%s: invalid volume.",
1353
0
     function );
1354
1355
0
    return( -1 );
1356
0
  }
1357
357
  internal_volume = (libfshfs_internal_volume_t *) volume;
1358
1359
357
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1360
357
  if( libcthreads_read_write_lock_grab_for_read(
1361
357
       internal_volume->read_write_lock,
1362
357
       error ) != 1 )
1363
0
  {
1364
0
    libcerror_error_set(
1365
0
     error,
1366
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1367
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1368
0
     "%s: unable to grab read/write lock for reading.",
1369
0
     function );
1370
1371
0
    return( -1 );
1372
0
  }
1373
357
#endif
1374
357
  if( internal_volume->root_directory_entry != NULL )
1375
204
  {
1376
204
    result = libfshfs_directory_entry_get_utf8_name_size(
1377
204
              internal_volume->root_directory_entry,
1378
204
              utf8_string_size,
1379
204
              error );
1380
204
  }
1381
153
  else
1382
153
  {
1383
153
    result = libfshfs_master_directory_block_get_utf8_volume_label_size(
1384
153
              internal_volume->master_directory_block,
1385
153
              utf8_string_size,
1386
153
              error );
1387
153
  }
1388
357
  if( result != 1 )
1389
153
  {
1390
153
    libcerror_error_set(
1391
153
     error,
1392
153
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1393
153
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1394
153
     "%s: unable to retrieve UTF-8 string size.",
1395
153
     function );
1396
1397
153
    result = -1;
1398
153
  }
1399
357
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1400
357
  if( libcthreads_read_write_lock_release_for_read(
1401
357
       internal_volume->read_write_lock,
1402
357
       error ) != 1 )
1403
0
  {
1404
0
    libcerror_error_set(
1405
0
     error,
1406
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1407
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1408
0
     "%s: unable to release read/write lock for reading.",
1409
0
     function );
1410
1411
0
    return( -1 );
1412
0
  }
1413
357
#endif
1414
357
  return( result );
1415
357
}
1416
1417
/* Retrieves the UTF-8 encoded name
1418
 * The size should include the end of string character
1419
 * Returns 1 if successful or -1 on error
1420
 */
1421
int libfshfs_volume_get_utf8_name(
1422
     libfshfs_volume_t *volume,
1423
     uint8_t *utf8_string,
1424
     size_t utf8_string_size,
1425
     libcerror_error_t **error )
1426
357
{
1427
357
  libfshfs_internal_volume_t *internal_volume = NULL;
1428
357
  static char *function                       = "libfshfs_volume_get_utf8_name";
1429
357
  int result                                  = 1;
1430
1431
357
  if( volume == NULL )
1432
0
  {
1433
0
    libcerror_error_set(
1434
0
     error,
1435
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1436
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1437
0
     "%s: invalid volume.",
1438
0
     function );
1439
1440
0
    return( -1 );
1441
0
  }
1442
357
  internal_volume = (libfshfs_internal_volume_t *) volume;
1443
1444
357
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1445
357
  if( libcthreads_read_write_lock_grab_for_read(
1446
357
       internal_volume->read_write_lock,
1447
357
       error ) != 1 )
1448
0
  {
1449
0
    libcerror_error_set(
1450
0
     error,
1451
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1452
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1453
0
     "%s: unable to grab read/write lock for reading.",
1454
0
     function );
1455
1456
0
    return( -1 );
1457
0
  }
1458
357
#endif
1459
357
  if( internal_volume->root_directory_entry != NULL )
1460
204
  {
1461
204
    result = libfshfs_directory_entry_get_utf8_name(
1462
204
              internal_volume->root_directory_entry,
1463
204
              utf8_string,
1464
204
              utf8_string_size,
1465
204
              error );
1466
204
  }
1467
153
  else
1468
153
  {
1469
153
    result = libfshfs_master_directory_block_get_utf8_volume_label(
1470
153
              internal_volume->master_directory_block,
1471
153
              utf8_string,
1472
153
              utf8_string_size,
1473
153
              error );
1474
153
  }
1475
357
  if( result != 1 )
1476
334
  {
1477
334
    libcerror_error_set(
1478
334
     error,
1479
334
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1480
334
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1481
334
     "%s: unable to retrieve UTF-8 string.",
1482
334
     function );
1483
1484
334
    result = -1;
1485
334
  }
1486
357
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1487
357
  if( libcthreads_read_write_lock_release_for_read(
1488
357
       internal_volume->read_write_lock,
1489
357
       error ) != 1 )
1490
0
  {
1491
0
    libcerror_error_set(
1492
0
     error,
1493
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1494
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1495
0
     "%s: unable to release read/write lock for reading.",
1496
0
     function );
1497
1498
0
    return( -1 );
1499
0
  }
1500
357
#endif
1501
357
  return( result );
1502
357
}
1503
1504
/* Retrieves the size of the UTF-16 encoded name
1505
 * The returned size includes the end of string character
1506
 * Returns 1 if successful or -1 on error
1507
 */
1508
int libfshfs_volume_get_utf16_name_size(
1509
     libfshfs_volume_t *volume,
1510
     size_t *utf16_string_size,
1511
     libcerror_error_t **error )
1512
0
{
1513
0
  libfshfs_internal_volume_t *internal_volume = NULL;
1514
0
  static char *function                       = "libfshfs_volume_get_utf16_name_size";
1515
0
  int result                                  = 1;
1516
1517
0
  if( volume == NULL )
1518
0
  {
1519
0
    libcerror_error_set(
1520
0
     error,
1521
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1522
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1523
0
     "%s: invalid volume.",
1524
0
     function );
1525
1526
0
    return( -1 );
1527
0
  }
1528
0
  internal_volume = (libfshfs_internal_volume_t *) volume;
1529
1530
0
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1531
0
  if( libcthreads_read_write_lock_grab_for_read(
1532
0
       internal_volume->read_write_lock,
1533
0
       error ) != 1 )
1534
0
  {
1535
0
    libcerror_error_set(
1536
0
     error,
1537
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1538
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1539
0
     "%s: unable to grab read/write lock for reading.",
1540
0
     function );
1541
1542
0
    return( -1 );
1543
0
  }
1544
0
#endif
1545
0
  if( internal_volume->root_directory_entry != NULL )
1546
0
  {
1547
0
    result = libfshfs_directory_entry_get_utf16_name_size(
1548
0
              internal_volume->root_directory_entry,
1549
0
              utf16_string_size,
1550
0
              error );
1551
0
  }
1552
0
  else
1553
0
  {
1554
0
    result = libfshfs_master_directory_block_get_utf16_volume_label_size(
1555
0
              internal_volume->master_directory_block,
1556
0
              utf16_string_size,
1557
0
              error );
1558
0
  }
1559
0
  if( result != 1 )
1560
0
  {
1561
0
    libcerror_error_set(
1562
0
     error,
1563
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1564
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1565
0
     "%s: unable to retrieve UTF-16 string size.",
1566
0
     function );
1567
1568
0
    result = -1;
1569
0
  }
1570
0
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1571
0
  if( libcthreads_read_write_lock_release_for_read(
1572
0
       internal_volume->read_write_lock,
1573
0
       error ) != 1 )
1574
0
  {
1575
0
    libcerror_error_set(
1576
0
     error,
1577
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1578
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1579
0
     "%s: unable to release read/write lock for reading.",
1580
0
     function );
1581
1582
0
    return( -1 );
1583
0
  }
1584
0
#endif
1585
0
  return( result );
1586
0
}
1587
1588
/* Retrieves the UTF-16 encoded name
1589
 * The size should include the end of string character
1590
 * Returns 1 if successful or -1 on error
1591
 */
1592
int libfshfs_volume_get_utf16_name(
1593
     libfshfs_volume_t *volume,
1594
     uint16_t *utf16_string,
1595
     size_t utf16_string_size,
1596
     libcerror_error_t **error )
1597
0
{
1598
0
  libfshfs_internal_volume_t *internal_volume = NULL;
1599
0
  static char *function                       = "libfshfs_volume_get_utf16_name";
1600
0
  int result                                  = 1;
1601
1602
0
  if( volume == NULL )
1603
0
  {
1604
0
    libcerror_error_set(
1605
0
     error,
1606
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1607
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1608
0
     "%s: invalid volume.",
1609
0
     function );
1610
1611
0
    return( -1 );
1612
0
  }
1613
0
  internal_volume = (libfshfs_internal_volume_t *) volume;
1614
1615
0
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1616
0
  if( libcthreads_read_write_lock_grab_for_read(
1617
0
       internal_volume->read_write_lock,
1618
0
       error ) != 1 )
1619
0
  {
1620
0
    libcerror_error_set(
1621
0
     error,
1622
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1623
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1624
0
     "%s: unable to grab read/write lock for reading.",
1625
0
     function );
1626
1627
0
    return( -1 );
1628
0
  }
1629
0
#endif
1630
0
  if( internal_volume->root_directory_entry != NULL )
1631
0
  {
1632
0
    result = libfshfs_directory_entry_get_utf16_name(
1633
0
              internal_volume->root_directory_entry,
1634
0
              utf16_string,
1635
0
              utf16_string_size,
1636
0
              error );
1637
0
  }
1638
0
  else
1639
0
  {
1640
0
    result = libfshfs_master_directory_block_get_utf16_volume_label(
1641
0
              internal_volume->master_directory_block,
1642
0
              utf16_string,
1643
0
              utf16_string_size,
1644
0
              error );
1645
0
  }
1646
0
  if( result != 1 )
1647
0
  {
1648
0
    libcerror_error_set(
1649
0
     error,
1650
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1651
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1652
0
     "%s: unable to retrieve UTF-16 string.",
1653
0
     function );
1654
1655
0
    result = -1;
1656
0
  }
1657
0
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1658
0
  if( libcthreads_read_write_lock_release_for_read(
1659
0
       internal_volume->read_write_lock,
1660
0
       error ) != 1 )
1661
0
  {
1662
0
    libcerror_error_set(
1663
0
     error,
1664
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1665
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1666
0
     "%s: unable to release read/write lock for reading.",
1667
0
     function );
1668
1669
0
    return( -1 );
1670
0
  }
1671
0
#endif
1672
0
  return( result );
1673
0
}
1674
1675
/* Retrieves the root directory file entry
1676
 * Returns 1 if successful or -1 on error
1677
 */
1678
int libfshfs_volume_get_root_directory(
1679
     libfshfs_volume_t *volume,
1680
     libfshfs_file_entry_t **file_entry,
1681
     libcerror_error_t **error )
1682
1.46k
{
1683
1.46k
  libfshfs_directory_entry_t *safe_directory_entry = NULL;
1684
1.46k
  libfshfs_internal_volume_t *internal_volume      = NULL;
1685
1.46k
  static char *function                            = "libfshfs_volume_get_root_directory";
1686
1.46k
  int result                                       = 1;
1687
1688
1.46k
  if( volume == NULL )
1689
0
  {
1690
0
    libcerror_error_set(
1691
0
     error,
1692
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1693
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1694
0
     "%s: invalid volume.",
1695
0
     function );
1696
1697
0
    return( -1 );
1698
0
  }
1699
1.46k
  internal_volume = (libfshfs_internal_volume_t *) volume;
1700
1701
1.46k
  if( file_entry == NULL )
1702
0
  {
1703
0
    libcerror_error_set(
1704
0
     error,
1705
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1706
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1707
0
     "%s: invalid file entry.",
1708
0
     function );
1709
1710
0
    return( -1 );
1711
0
  }
1712
1.46k
  if( *file_entry != NULL )
1713
0
  {
1714
0
    libcerror_error_set(
1715
0
     error,
1716
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1717
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1718
0
     "%s: invalid file entry value already set.",
1719
0
     function );
1720
1721
0
    return( -1 );
1722
0
  }
1723
1.46k
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1724
1.46k
  if( libcthreads_read_write_lock_grab_for_read(
1725
1.46k
       internal_volume->read_write_lock,
1726
1.46k
       error ) != 1 )
1727
0
  {
1728
0
    libcerror_error_set(
1729
0
     error,
1730
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1731
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1732
0
     "%s: unable to grab read/write lock for reading.",
1733
0
     function );
1734
1735
0
    return( -1 );
1736
0
  }
1737
1.46k
#endif
1738
1.46k
  if( libfshfs_directory_entry_clone(
1739
1.46k
       &safe_directory_entry,
1740
1.46k
       internal_volume->root_directory_entry,
1741
1.46k
       error ) != 1 )
1742
0
  {
1743
0
    libcerror_error_set(
1744
0
     error,
1745
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1746
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1747
0
     "%s: unable to clone root directory entry.",
1748
0
     function );
1749
1750
0
    result = -1;
1751
0
  }
1752
1.46k
  else
1753
1.46k
  {
1754
    /* libfshfs_file_entry_initialize takes over management of directory_entry
1755
     */
1756
1.46k
    if( libfshfs_file_entry_initialize(
1757
1.46k
         file_entry,
1758
1.46k
         internal_volume->io_handle,
1759
1.46k
         internal_volume->file_io_handle,
1760
1.46k
         internal_volume->file_system,
1761
1.46k
         safe_directory_entry,
1762
1.46k
         error ) != 1 )
1763
160
    {
1764
160
      libcerror_error_set(
1765
160
       error,
1766
160
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1767
160
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1768
160
       "%s: unable to create file entry.",
1769
160
       function );
1770
1771
160
      libfshfs_directory_entry_free(
1772
160
       &safe_directory_entry,
1773
160
       NULL );
1774
1775
160
      result = -1;
1776
160
    }
1777
1.46k
  }
1778
1.46k
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1779
1.46k
  if( libcthreads_read_write_lock_release_for_read(
1780
1.46k
       internal_volume->read_write_lock,
1781
1.46k
       error ) != 1 )
1782
0
  {
1783
0
    libcerror_error_set(
1784
0
     error,
1785
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1786
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1787
0
     "%s: unable to release read/write lock for reading.",
1788
0
     function );
1789
1790
0
    return( -1 );
1791
0
  }
1792
1.46k
#endif
1793
1.46k
  return( result );
1794
1.46k
}
1795
1796
/* Retrieves the file entry for a specific identifier (or catalog node identifier (CNID))
1797
 * Returns 1 if successful, 0 if not available or -1 on error
1798
 */
1799
int libfshfs_volume_get_file_entry_by_identifier(
1800
     libfshfs_volume_t *volume,
1801
     uint32_t identifier,
1802
     libfshfs_file_entry_t **file_entry,
1803
     libcerror_error_t **error )
1804
0
{
1805
0
  libfshfs_directory_entry_t *directory_entry = NULL;
1806
0
  libfshfs_internal_volume_t *internal_volume = NULL;
1807
0
  static char *function                       = "libfshfs_volume_get_file_entry_by_identifier";
1808
0
  int result                                  = 0;
1809
1810
0
  if( volume == NULL )
1811
0
  {
1812
0
    libcerror_error_set(
1813
0
     error,
1814
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1815
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1816
0
     "%s: invalid volume.",
1817
0
     function );
1818
1819
0
    return( -1 );
1820
0
  }
1821
0
  internal_volume = (libfshfs_internal_volume_t *) volume;
1822
1823
0
  if( file_entry == NULL )
1824
0
  {
1825
0
    libcerror_error_set(
1826
0
     error,
1827
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1828
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1829
0
     "%s: invalid file entry.",
1830
0
     function );
1831
1832
0
    return( -1 );
1833
0
  }
1834
0
  if( *file_entry != NULL )
1835
0
  {
1836
0
    libcerror_error_set(
1837
0
     error,
1838
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1839
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1840
0
     "%s: invalid file entry value already set.",
1841
0
     function );
1842
1843
0
    return( -1 );
1844
0
  }
1845
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1846
  if( libcthreads_read_write_lock_grab_for_write(
1847
       internal_volume->read_write_lock,
1848
       error ) != 1 )
1849
  {
1850
    libcerror_error_set(
1851
     error,
1852
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1853
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1854
     "%s: unable to grab read/write lock for writing.",
1855
     function );
1856
1857
    return( -1 );
1858
  }
1859
#endif
1860
0
  result = libfshfs_file_system_get_directory_entry_by_identifier(
1861
0
            internal_volume->file_system,
1862
0
            internal_volume->io_handle,
1863
0
            internal_volume->file_io_handle,
1864
0
            identifier,
1865
0
            &directory_entry,
1866
0
            error );
1867
1868
0
  if( result == -1 )
1869
0
  {
1870
0
    libcerror_error_set(
1871
0
     error,
1872
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1873
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1874
0
     "%s: unable to retrieve directory entry: %" PRIu32 ".",
1875
0
     function,
1876
0
     identifier );
1877
1878
0
    result = -1;
1879
0
  }
1880
0
  else if( result != 0 )
1881
0
  {
1882
    /* libfshfs_file_entry_initialize takes over management of directory_entry
1883
     */
1884
0
    if( libfshfs_file_entry_initialize(
1885
0
         file_entry,
1886
0
         internal_volume->io_handle,
1887
0
         internal_volume->file_io_handle,
1888
0
         internal_volume->file_system,
1889
0
         directory_entry,
1890
0
         error ) != 1 )
1891
0
    {
1892
0
      libcerror_error_set(
1893
0
       error,
1894
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1895
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1896
0
       "%s: unable to create file entry.",
1897
0
       function );
1898
1899
0
      libfshfs_directory_entry_free(
1900
0
       &directory_entry,
1901
0
       NULL );
1902
1903
0
      result = -1;
1904
0
    }
1905
0
  }
1906
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1907
  if( libcthreads_read_write_lock_release_for_write(
1908
       internal_volume->read_write_lock,
1909
       error ) != 1 )
1910
  {
1911
    libcerror_error_set(
1912
     error,
1913
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1914
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1915
     "%s: unable to release read/write lock for writing.",
1916
     function );
1917
1918
    return( -1 );
1919
  }
1920
#endif
1921
0
  return( result );
1922
0
}
1923
1924
/* Retrieves the file entry for an UTF-8 encoded path
1925
 * Returns 1 if successful, 0 if no such file entry or -1 on error
1926
 */
1927
int libfshfs_volume_get_file_entry_by_utf8_path(
1928
     libfshfs_volume_t *volume,
1929
     const uint8_t *utf8_string,
1930
     size_t utf8_string_length,
1931
     libfshfs_file_entry_t **file_entry,
1932
     libcerror_error_t **error )
1933
894
{
1934
894
  libfshfs_directory_entry_t *directory_entry = NULL;
1935
894
  libfshfs_internal_volume_t *internal_volume = NULL;
1936
894
  static char *function                       = "libfshfs_volume_get_file_entry_by_utf8_path";
1937
894
  int result                                  = 0;
1938
1939
894
  if( volume == NULL )
1940
0
  {
1941
0
    libcerror_error_set(
1942
0
     error,
1943
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1944
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1945
0
     "%s: invalid volume.",
1946
0
     function );
1947
1948
0
    return( -1 );
1949
0
  }
1950
894
  internal_volume = (libfshfs_internal_volume_t *) volume;
1951
1952
894
  if( file_entry == NULL )
1953
0
  {
1954
0
    libcerror_error_set(
1955
0
     error,
1956
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1957
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1958
0
     "%s: invalid file entry.",
1959
0
     function );
1960
1961
0
    return( -1 );
1962
0
  }
1963
894
  if( *file_entry != NULL )
1964
0
  {
1965
0
    libcerror_error_set(
1966
0
     error,
1967
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1968
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1969
0
     "%s: invalid file entry value already set.",
1970
0
     function );
1971
1972
0
    return( -1 );
1973
0
  }
1974
894
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
1975
894
  if( libcthreads_read_write_lock_grab_for_write(
1976
894
       internal_volume->read_write_lock,
1977
894
       error ) != 1 )
1978
0
  {
1979
0
    libcerror_error_set(
1980
0
     error,
1981
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1982
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1983
0
     "%s: unable to grab read/write lock for writing.",
1984
0
     function );
1985
1986
0
    return( -1 );
1987
0
  }
1988
894
#endif
1989
894
  result = libfshfs_file_system_get_directory_entry_by_utf8_path(
1990
894
            internal_volume->file_system,
1991
894
            internal_volume->io_handle,
1992
894
            internal_volume->file_io_handle,
1993
894
            utf8_string,
1994
894
            utf8_string_length,
1995
894
            &directory_entry,
1996
894
            error );
1997
1998
894
  if( result == -1 )
1999
250
  {
2000
250
    libcerror_error_set(
2001
250
     error,
2002
250
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2003
250
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2004
250
     "%s: unable to retrieve directory entry.",
2005
250
     function );
2006
2007
250
    result = -1;
2008
250
  }
2009
644
  else if( result != 0 )
2010
258
  {
2011
    /* libfshfs_file_entry_initialize takes over management of directory_entry
2012
     */
2013
258
    if( libfshfs_file_entry_initialize(
2014
258
         file_entry,
2015
258
         internal_volume->io_handle,
2016
258
         internal_volume->file_io_handle,
2017
258
         internal_volume->file_system,
2018
258
         directory_entry,
2019
258
         error ) != 1 )
2020
0
    {
2021
0
      libcerror_error_set(
2022
0
       error,
2023
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2024
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2025
0
       "%s: unable to create file entry.",
2026
0
       function );
2027
2028
0
      libfshfs_directory_entry_free(
2029
0
       &directory_entry,
2030
0
       NULL );
2031
2032
0
      result = -1;
2033
0
    }
2034
258
  }
2035
894
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
2036
894
  if( libcthreads_read_write_lock_release_for_write(
2037
894
       internal_volume->read_write_lock,
2038
894
       error ) != 1 )
2039
0
  {
2040
0
    libcerror_error_set(
2041
0
     error,
2042
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2043
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2044
0
     "%s: unable to release read/write lock for writing.",
2045
0
     function );
2046
2047
0
    libfshfs_file_entry_free(
2048
0
     file_entry,
2049
0
     NULL );
2050
2051
0
    return( -1 );
2052
0
  }
2053
894
#endif
2054
894
  return( result );
2055
894
}
2056
2057
/* Retrieves the file entry for an UTF-16 encoded path
2058
 * Returns 1 if successful, 0 if no such file entry or -1 on error
2059
 */
2060
int libfshfs_volume_get_file_entry_by_utf16_path(
2061
     libfshfs_volume_t *volume,
2062
     const uint16_t *utf16_string,
2063
     size_t utf16_string_length,
2064
     libfshfs_file_entry_t **file_entry,
2065
     libcerror_error_t **error )
2066
0
{
2067
0
  libfshfs_directory_entry_t *directory_entry = NULL;
2068
0
  libfshfs_internal_volume_t *internal_volume = NULL;
2069
0
  static char *function                       = "libfshfs_volume_get_file_entry_by_utf16_path";
2070
0
  int result                                  = 0;
2071
2072
0
  if( volume == NULL )
2073
0
  {
2074
0
    libcerror_error_set(
2075
0
     error,
2076
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2077
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2078
0
     "%s: invalid volume.",
2079
0
     function );
2080
2081
0
    return( -1 );
2082
0
  }
2083
0
  internal_volume = (libfshfs_internal_volume_t *) volume;
2084
2085
0
  if( file_entry == NULL )
2086
0
  {
2087
0
    libcerror_error_set(
2088
0
     error,
2089
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2090
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2091
0
     "%s: invalid file entry.",
2092
0
     function );
2093
2094
0
    return( -1 );
2095
0
  }
2096
0
  if( *file_entry != NULL )
2097
0
  {
2098
0
    libcerror_error_set(
2099
0
     error,
2100
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2101
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2102
0
     "%s: invalid file entry value already set.",
2103
0
     function );
2104
2105
0
    return( -1 );
2106
0
  }
2107
0
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
2108
0
  if( libcthreads_read_write_lock_grab_for_write(
2109
0
       internal_volume->read_write_lock,
2110
0
       error ) != 1 )
2111
0
  {
2112
0
    libcerror_error_set(
2113
0
     error,
2114
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2115
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2116
0
     "%s: unable to grab read/write lock for writing.",
2117
0
     function );
2118
2119
0
    return( -1 );
2120
0
  }
2121
0
#endif
2122
0
  result = libfshfs_file_system_get_directory_entry_by_utf16_path(
2123
0
            internal_volume->file_system,
2124
0
            internal_volume->io_handle,
2125
0
            internal_volume->file_io_handle,
2126
0
            utf16_string,
2127
0
            utf16_string_length,
2128
0
            &directory_entry,
2129
0
            error );
2130
2131
0
  if( result == -1 )
2132
0
  {
2133
0
    libcerror_error_set(
2134
0
     error,
2135
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2136
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2137
0
     "%s: unable to retrieve directory entry.",
2138
0
     function );
2139
2140
0
    result = -1;
2141
0
  }
2142
0
  else if( result != 0 )
2143
0
  {
2144
    /* libfshfs_file_entry_initialize takes over management of directory_entry
2145
     */
2146
0
    if( libfshfs_file_entry_initialize(
2147
0
         file_entry,
2148
0
         internal_volume->io_handle,
2149
0
         internal_volume->file_io_handle,
2150
0
         internal_volume->file_system,
2151
0
         directory_entry,
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_INITIALIZE_FAILED,
2158
0
       "%s: unable to create file entry.",
2159
0
       function );
2160
2161
0
      libfshfs_directory_entry_free(
2162
0
       &directory_entry,
2163
0
       NULL );
2164
2165
0
      result = -1;
2166
0
    }
2167
0
  }
2168
0
#if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
2169
0
  if( libcthreads_read_write_lock_release_for_write(
2170
0
       internal_volume->read_write_lock,
2171
0
       error ) != 1 )
2172
0
  {
2173
0
    libcerror_error_set(
2174
0
     error,
2175
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2176
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2177
0
     "%s: unable to release read/write lock for writing.",
2178
0
     function );
2179
2180
0
    libfshfs_file_entry_free(
2181
0
     file_entry,
2182
0
     NULL );
2183
2184
0
    return( -1 );
2185
0
  }
2186
0
#endif
2187
0
  return( result );
2188
0
}
2189