Coverage Report

Created: 2025-06-13 07:22

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