Coverage Report

Created: 2025-10-14 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsext/libfsext/libfsext_volume.c
Line
Count
Source
1
/*
2
 * Volume functions
3
 *
4
 * Copyright (C) 2010-2025, 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.29k
{
52
5.29k
  libfsext_internal_volume_t *internal_volume = NULL;
53
5.29k
  static char *function                       = "libfsext_volume_initialize";
54
55
5.29k
  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.29k
  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.29k
  internal_volume = memory_allocate_structure(
78
5.29k
                     libfsext_internal_volume_t );
79
80
5.29k
  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.29k
  if( memory_set(
92
5.29k
       internal_volume,
93
5.29k
       0,
94
5.29k
       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.29k
  if( libfsext_io_handle_initialize(
109
5.29k
       &( internal_volume->io_handle ),
110
5.29k
       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.29k
  if( libcdata_array_initialize(
122
5.29k
       &( internal_volume->group_descriptors_array ),
123
5.29k
       0,
124
5.29k
       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.29k
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
136
5.29k
  if( libcthreads_read_write_lock_initialize(
137
5.29k
       &( internal_volume->read_write_lock ),
138
5.29k
       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.29k
#endif
150
5.29k
  *volume = (libfsext_volume_t *) internal_volume;
151
152
5.29k
  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.29k
}
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.29k
{
176
5.29k
  libfsext_internal_volume_t *internal_volume = NULL;
177
5.29k
  static char *function                       = "libfsext_volume_free";
178
5.29k
  int result                                  = 1;
179
180
5.29k
  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.29k
  if( *volume != NULL )
192
5.29k
  {
193
5.29k
    internal_volume = (libfsext_internal_volume_t *) *volume;
194
195
5.29k
    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.29k
    *volume = NULL;
212
213
5.29k
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
214
5.29k
    if( libcthreads_read_write_lock_free(
215
5.29k
         &( internal_volume->read_write_lock ),
216
5.29k
         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.29k
#endif
228
5.29k
    if( libcdata_array_free(
229
5.29k
         &( internal_volume->group_descriptors_array ),
230
5.29k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsext_group_descriptor_free,
231
5.29k
         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.29k
    if( libfsext_io_handle_free(
243
5.29k
         &( internal_volume->io_handle ),
244
5.29k
         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.29k
    memory_free(
256
5.29k
     internal_volume );
257
5.29k
  }
258
5.29k
  return( result );
259
5.29k
}
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.29k
{
647
5.29k
  libfsext_internal_volume_t *internal_volume = NULL;
648
5.29k
  static char *function                       = "libfsext_volume_open_file_io_handle";
649
5.29k
  uint8_t file_io_handle_opened_in_library    = 0;
650
5.29k
  int bfio_access_flags                       = 0;
651
5.29k
  int file_io_handle_is_open                  = 0;
652
653
5.29k
  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.29k
  internal_volume = (libfsext_internal_volume_t *) volume;
665
666
5.29k
  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.29k
  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.29k
  if( ( ( access_flags & LIBFSEXT_ACCESS_FLAG_READ ) == 0 )
689
0
   && ( ( 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.29k
  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.29k
  if( ( access_flags & LIBFSEXT_ACCESS_FLAG_READ ) != 0 )
712
5.29k
  {
713
5.29k
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
714
5.29k
  }
715
5.29k
  file_io_handle_is_open = libbfio_handle_is_open(
716
5.29k
                            file_io_handle,
717
5.29k
                            error );
718
719
5.29k
  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.29k
  else if( file_io_handle_is_open == 0 )
731
5.29k
  {
732
5.29k
    if( libbfio_handle_open(
733
5.29k
         file_io_handle,
734
5.29k
         bfio_access_flags,
735
5.29k
         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.29k
    file_io_handle_opened_in_library = 1;
747
5.29k
  }
748
5.29k
  if( libfsext_internal_volume_open_read(
749
5.29k
       internal_volume,
750
5.29k
       file_io_handle,
751
5.29k
       error ) != 1 )
752
1.59k
  {
753
1.59k
    libcerror_error_set(
754
1.59k
     error,
755
1.59k
     LIBCERROR_ERROR_DOMAIN_IO,
756
1.59k
     LIBCERROR_IO_ERROR_READ_FAILED,
757
1.59k
     "%s: unable to read from file IO handle.",
758
1.59k
     function );
759
760
1.59k
    goto on_error;
761
1.59k
  }
762
3.70k
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
763
3.70k
  if( libcthreads_read_write_lock_grab_for_write(
764
3.70k
       internal_volume->read_write_lock,
765
3.70k
       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.70k
#endif
777
3.70k
  internal_volume->file_io_handle                   = file_io_handle;
778
3.70k
  internal_volume->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
779
780
3.70k
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
781
3.70k
  if( libcthreads_read_write_lock_release_for_write(
782
3.70k
       internal_volume->read_write_lock,
783
3.70k
       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.70k
#endif
798
3.70k
  return( 1 );
799
800
1.59k
on_error:
801
1.59k
  if( file_io_handle_opened_in_library != 0 )
802
1.59k
  {
803
1.59k
    libbfio_handle_close(
804
1.59k
     file_io_handle,
805
1.59k
     error );
806
1.59k
  }
807
1.59k
  return( -1 );
808
3.70k
}
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.70k
{
817
3.70k
  libfsext_internal_volume_t *internal_volume = NULL;
818
3.70k
  static char *function                       = "libfsext_volume_close";
819
3.70k
  int result                                  = 0;
820
821
3.70k
  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.70k
  internal_volume = (libfsext_internal_volume_t *) volume;
833
834
3.70k
  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.70k
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
846
3.70k
  if( libcthreads_read_write_lock_grab_for_write(
847
3.70k
       internal_volume->read_write_lock,
848
3.70k
       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.70k
#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.70k
  if( internal_volume->file_io_handle_opened_in_library != 0 )
882
3.70k
  {
883
3.70k
    if( libbfio_handle_close(
884
3.70k
         internal_volume->file_io_handle,
885
3.70k
         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.70k
    internal_volume->file_io_handle_opened_in_library = 0;
897
3.70k
  }
898
3.70k
  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.70k
  internal_volume->file_io_handle = NULL;
916
917
3.70k
  if( libfsext_io_handle_clear(
918
3.70k
       internal_volume->io_handle,
919
3.70k
       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.70k
  if( internal_volume->superblock != NULL )
931
3.70k
  {
932
3.70k
    if( libfsext_superblock_free(
933
3.70k
         &( internal_volume->superblock ),
934
3.70k
         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.70k
  }
946
3.70k
  if( libcdata_array_empty(
947
3.70k
       internal_volume->group_descriptors_array,
948
3.70k
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsext_group_descriptor_free,
949
3.70k
       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.70k
  if( internal_volume->inode_table != NULL )
961
3.70k
  {
962
3.70k
    if( libfsext_inode_table_free(
963
3.70k
         &( internal_volume->inode_table ),
964
3.70k
         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.70k
  }
976
3.70k
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
977
3.70k
  if( libcthreads_read_write_lock_release_for_write(
978
3.70k
       internal_volume->read_write_lock,
979
3.70k
       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.70k
#endif
991
3.70k
  return( result );
992
3.70k
}
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.29k
{
1002
5.29k
  static char *function = "libfsext_internal_volume_open_read";
1003
1004
5.29k
  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.29k
  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.29k
  if( libfsext_internal_volume_read_block_groups(
1027
5.29k
       internal_volume,
1028
5.29k
       file_io_handle,
1029
5.29k
       error ) != 1 )
1030
1.16k
  {
1031
1.16k
    libcerror_error_set(
1032
1.16k
     error,
1033
1.16k
     LIBCERROR_ERROR_DOMAIN_IO,
1034
1.16k
     LIBCERROR_IO_ERROR_READ_FAILED,
1035
1.16k
     "%s: unable to read block groups.",
1036
1.16k
     function );
1037
1038
1.16k
    goto on_error;
1039
1.16k
  }
1040
4.12k
  if( libfsext_inode_table_initialize(
1041
4.12k
       &( internal_volume->inode_table ),
1042
4.12k
       internal_volume->io_handle->inode_size,
1043
4.12k
       internal_volume->io_handle,
1044
4.12k
       internal_volume->superblock,
1045
4.12k
       internal_volume->group_descriptors_array,
1046
4.12k
       error ) != 1 )
1047
429
  {
1048
429
    libcerror_error_set(
1049
429
     error,
1050
429
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1051
429
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1052
429
     "%s: unable to create inode table.",
1053
429
     function );
1054
1055
429
    goto on_error;
1056
429
  }
1057
3.70k
  return( 1 );
1058
1059
1.59k
on_error:
1060
1.59k
  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.59k
  libcdata_array_empty(
1067
1.59k
   internal_volume->group_descriptors_array,
1068
1.59k
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsext_group_descriptor_free,
1069
1.59k
   NULL );
1070
1071
1.59k
  if( internal_volume->superblock != NULL )
1072
923
  {
1073
923
    libfsext_superblock_free(
1074
923
     &( internal_volume->superblock ),
1075
923
     NULL );
1076
923
  }
1077
1.59k
  return( -1 );
1078
4.12k
}
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.29k
{
1088
5.29k
  libfsext_bitmap_t *bitmap                        = NULL;
1089
5.29k
  libfsext_group_descriptor_t *group_descriptor    = NULL;
1090
5.29k
  libfsext_superblock_t *superblock                = NULL;
1091
5.29k
  static char *function                            = "libfsext_internal_volume_read_block_groups";
1092
5.29k
  size64_t block_group_size                        = 0;
1093
5.29k
  size_t group_descriptor_data_size                = 0;
1094
5.29k
  off64_t block_group_offset                       = 0;
1095
5.29k
  off64_t group_descriptor_offset                  = 0;
1096
5.29k
  off64_t superblock_offset                        = 0;
1097
5.29k
  uint32_t block_group_number                      = 0;
1098
5.29k
  uint32_t exponent3                               = 3;
1099
5.29k
  uint32_t exponent5                               = 5;
1100
5.29k
  uint32_t exponent7                               = 7;
1101
5.29k
  uint32_t first_group_number                      = 0;
1102
5.29k
  uint32_t group_descriptor_index                  = 0;
1103
5.29k
  uint32_t meta_group_number                       = 0;
1104
5.29k
  uint32_t metadata_block_group_number             = 0;
1105
5.29k
  uint32_t metadata_block_group_start_block_number = 0;
1106
5.29k
  uint32_t number_of_block_groups                  = 0;
1107
5.29k
  uint32_t number_of_blocks_per_meta_group         = 0;
1108
5.29k
  uint32_t number_of_group_descriptors             = 0;
1109
5.29k
  uint32_t superblock_number                       = 0;
1110
5.29k
  uint8_t block_group_has_group_descriptors        = 0;
1111
5.29k
  uint8_t block_group_has_superblock               = 0;
1112
5.29k
  uint8_t is_primary_group_descriptor_table        = 0;
1113
5.29k
  int entry_index                                  = 0;
1114
5.29k
  int has_sparse_superblock                        = 0;
1115
5.29k
  int result                                       = 0;
1116
1117
#ifdef TODO
1118
  off64_t block_bitmap_offset                      = 0;
1119
  off64_t inode_bitmap_offset                      = 0;
1120
#endif
1121
1122
5.29k
  if( internal_volume == NULL )
1123
0
  {
1124
0
    libcerror_error_set(
1125
0
     error,
1126
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1127
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1128
0
     "%s: invalid internal volume.",
1129
0
     function );
1130
1131
0
    return( -1 );
1132
0
  }
1133
5.29k
  if( internal_volume->io_handle == NULL )
1134
0
  {
1135
0
    libcerror_error_set(
1136
0
     error,
1137
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1138
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1139
0
     "%s: invalid internal volume - missing IO handle.",
1140
0
     function );
1141
1142
0
    return( -1 );
1143
0
  }
1144
5.29k
  if( internal_volume->superblock != NULL )
1145
0
  {
1146
0
    libcerror_error_set(
1147
0
     error,
1148
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1149
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1150
0
     "%s: invalid volume - superblock value already set.",
1151
0
     function );
1152
1153
0
    return( -1 );
1154
0
  }
1155
#if SIZEOF_SIZE_T <= 4
1156
  if( internal_volume->io_handle->block_size > (uint32_t) SSIZE_MAX )
1157
  {
1158
    libcerror_error_set(
1159
     error,
1160
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1161
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1162
     "%s: invalid internal volume - invalid IO handle - block size value exceeds maximum.",
1163
     function );
1164
1165
    return( -1 );
1166
  }
1167
#endif
1168
5.29k
  do
1169
1.58M
  {
1170
1.58M
    if( exponent7 < block_group_number )
1171
800
    {
1172
800
      exponent7 *= 7;
1173
800
    }
1174
1.58M
    if( exponent5 < block_group_number )
1175
1.10k
    {
1176
1.10k
      exponent5 *= 5;
1177
1.10k
    }
1178
1.58M
    if( exponent3 < block_group_number )
1179
1.71k
    {
1180
1.71k
      exponent3 *= 3;
1181
1.71k
    }
1182
1.58M
    block_group_has_superblock = 0;
1183
1184
1.58M
    if( block_group_number == 0 )
1185
5.29k
    {
1186
5.29k
      block_group_has_superblock = 1;
1187
5.29k
    }
1188
1.57M
    else if( has_sparse_superblock != 0 )
1189
1.45M
    {
1190
1.45M
      if( ( block_group_number == 1 )
1191
1.45M
       || ( block_group_number == exponent3 )
1192
1.45M
       || ( block_group_number == exponent5 )
1193
1.45M
       || ( block_group_number == exponent7 ) )
1194
3.33k
      {
1195
3.33k
        block_group_has_superblock = 1;
1196
3.33k
      }
1197
1.45M
    }
1198
1.58M
    if( block_group_has_superblock != 0 )
1199
8.63k
    {
1200
8.63k
      superblock_offset = block_group_offset;
1201
1202
8.63k
      if( internal_volume->io_handle->block_size > 0 )
1203
3.33k
      {
1204
3.33k
        superblock_number = superblock_offset / internal_volume->io_handle->block_size;
1205
3.33k
      }
1206
8.63k
      if( ( block_group_offset == 0 )
1207
261
       || ( internal_volume->io_handle->block_size == 1024 ) )
1208
8.56k
      {
1209
8.56k
        superblock_offset += 1024;
1210
8.56k
      }
1211
#if defined( HAVE_DEBUG_OUTPUT )
1212
      if( libcnotify_verbose != 0 )
1213
      {
1214
        libcnotify_printf(
1215
         "Reading block group: %" PRIu32 " superblock: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
1216
         block_group_number,
1217
         superblock_number,
1218
         superblock_offset,
1219
         superblock_offset );
1220
      }
1221
#endif
1222
8.63k
      if( libfsext_superblock_initialize(
1223
8.63k
           &superblock,
1224
8.63k
           error ) != 1 )
1225
0
      {
1226
0
        libcerror_error_set(
1227
0
         error,
1228
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1229
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1230
0
         "%s: unable to create superblock.",
1231
0
         function );
1232
1233
0
        goto on_error;
1234
0
      }
1235
8.63k
      result = libfsext_superblock_read_file_io_handle(
1236
8.63k
                superblock,
1237
8.63k
                file_io_handle,
1238
8.63k
                superblock_offset,
1239
8.63k
                error );
1240
1241
8.63k
      if( block_group_number == 0 )
1242
5.29k
      {
1243
5.29k
        if( result != 1 )
1244
666
        {
1245
666
          libcerror_error_set(
1246
666
           error,
1247
666
           LIBCERROR_ERROR_DOMAIN_IO,
1248
666
           LIBCERROR_IO_ERROR_READ_FAILED,
1249
666
           "%s: unable to read block group: %" PRIu32 " superblock: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1250
666
           function,
1251
666
           block_group_number,
1252
666
           superblock_number,
1253
666
           superblock_offset,
1254
666
           superblock_offset );
1255
1256
666
          goto on_error;
1257
666
        }
1258
4.63k
        number_of_block_groups = superblock->number_of_block_groups;
1259
4.63k
        block_group_size       = superblock->block_group_size;
1260
1261
4.63k
        if( ( superblock->incompatible_features_flags & LIBFSEXT_INCOMPATIBLE_FEATURES_FLAG_HAS_META_BLOCK_GROUPS ) != 0 )
1262
467
        {
1263
467
          if( ( ( superblock->incompatible_features_flags & LIBFSEXT_INCOMPATIBLE_FEATURES_FLAG_64BIT_SUPPORT ) != 0 )
1264
293
            && ( superblock->group_descriptor_size > 32 ) )
1265
133
          {
1266
133
            group_descriptor_data_size = 64;
1267
133
          }
1268
334
          else
1269
334
          {
1270
334
            group_descriptor_data_size = 32;
1271
334
          }
1272
467
          number_of_blocks_per_meta_group = superblock->block_size / group_descriptor_data_size;
1273
1274
467
          if( superblock->first_metadata_block_group > ( (uint32_t) UINT32_MAX / number_of_blocks_per_meta_group ) )
1275
8
          {
1276
8
            libcerror_error_set(
1277
8
             error,
1278
8
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1279
8
             LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1280
8
             "%s: invalid first metadata block group value out of bounds.",
1281
8
             function );
1282
1283
8
            goto on_error;
1284
8
          }
1285
459
          metadata_block_group_start_block_number = superblock->first_metadata_block_group * number_of_blocks_per_meta_group;
1286
459
        }
1287
4.62k
        internal_volume->io_handle->block_size                          = superblock->block_size;
1288
4.62k
        internal_volume->io_handle->inode_size                          = superblock->inode_size;
1289
4.62k
        internal_volume->io_handle->group_descriptor_size               = superblock->group_descriptor_size;
1290
4.62k
        internal_volume->io_handle->format_revision                     = superblock->format_revision;
1291
4.62k
        internal_volume->io_handle->compatible_features_flags           = superblock->compatible_features_flags;
1292
4.62k
        internal_volume->io_handle->incompatible_features_flags         = superblock->incompatible_features_flags;
1293
4.62k
        internal_volume->io_handle->read_only_compatible_features_flags = superblock->read_only_compatible_features_flags;
1294
4.62k
        internal_volume->io_handle->format_version                      = superblock->format_version;
1295
1296
4.62k
        if( libfsext_checksum_calculate_crc32(
1297
4.62k
             &( internal_volume->io_handle->metadata_checksum_seed ),
1298
4.62k
             superblock->file_system_identifier,
1299
4.62k
             16,
1300
4.62k
             0,
1301
4.62k
             error ) != 1 )
1302
0
        {
1303
0
          libcerror_error_set(
1304
0
           error,
1305
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1306
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1307
0
           "%s: unable to calculate CRC-32.",
1308
0
           function );
1309
1310
0
          goto on_error;
1311
0
        }
1312
4.62k
        internal_volume->superblock = superblock;
1313
4.62k
        superblock                  = NULL;
1314
1315
4.62k
        has_sparse_superblock = ( internal_volume->io_handle->read_only_compatible_features_flags & LIBFSEXT_READ_ONLY_COMPATIBLE_FEATURES_FLAG_SPARSE_SUPERBLOCK ) != 0;
1316
4.62k
      }
1317
3.33k
      else
1318
3.33k
      {
1319
3.33k
        if( result == -1 )
1320
103
        {
1321
103
          libcerror_error_set(
1322
103
           error,
1323
103
           LIBCERROR_ERROR_DOMAIN_IO,
1324
103
           LIBCERROR_IO_ERROR_READ_FAILED,
1325
103
           "%s: unable to read block group: %" PRIu32 " superblock: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1326
103
           function,
1327
103
           block_group_number,
1328
103
           superblock_number,
1329
103
           superblock_offset,
1330
103
           superblock_offset );
1331
1332
103
          goto on_error;
1333
103
        }
1334
        /* Ignore backup superblocks without a correct signature
1335
         */
1336
3.23k
        else if( result == 1 )
1337
3.12k
        {
1338
/* TODO compare superblocks */
1339
3.12k
        }
1340
3.23k
        if( libfsext_superblock_free(
1341
3.23k
             &superblock,
1342
3.23k
             error ) != 1 )
1343
0
        {
1344
0
          libcerror_error_set(
1345
0
           error,
1346
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1347
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1348
0
           "%s: unable to free superblock.",
1349
0
           function );
1350
1351
0
          goto on_error;
1352
0
        }
1353
3.23k
      }
1354
8.63k
    }
1355
    /* When the has meta block groups feature is enabled group descriptors
1356
     * are stored at the beginning of the first, second, and  last block
1357
     * groups in a meta block group, independent of a superblock. Otherwise
1358
     * group descriptors are stored in the first block after a superblock.
1359
     */
1360
1.58M
    if( ( number_of_blocks_per_meta_group == 0 )
1361
1.52M
     || ( block_group_number < metadata_block_group_start_block_number ) )
1362
85.3k
    {
1363
85.3k
      block_group_has_group_descriptors = block_group_has_superblock;
1364
85.3k
    }
1365
1.49M
    else
1366
1.49M
    {
1367
1.49M
      metadata_block_group_number = block_group_number % number_of_blocks_per_meta_group;
1368
1369
1.49M
      if( ( metadata_block_group_number == 0 )
1370
1.49M
       || ( metadata_block_group_number == 1 )
1371
1.49M
       || ( metadata_block_group_number == ( number_of_blocks_per_meta_group - 1 ) ) )
1372
8.90k
      {
1373
8.90k
        block_group_has_group_descriptors = 1;
1374
8.90k
      }
1375
1.48M
      else
1376
1.48M
      {
1377
1.48M
        block_group_has_group_descriptors = 0;
1378
1.48M
      }
1379
1.49M
    }
1380
1.58M
    if( block_group_has_group_descriptors != 0 )
1381
14.8k
    {
1382
14.8k
      group_descriptor_offset = block_group_offset;
1383
1384
14.8k
      if( internal_volume->io_handle->block_size == 1024 )
1385
6.14k
      {
1386
6.14k
        group_descriptor_offset += 1024;
1387
6.14k
      }
1388
14.8k
      if( block_group_has_superblock != 0 )
1389
6.31k
      {
1390
6.31k
        group_descriptor_offset += internal_volume->io_handle->block_size;
1391
6.31k
      }
1392
#if defined( HAVE_DEBUG_OUTPUT )
1393
      if( libcnotify_verbose != 0 )
1394
      {
1395
        libcnotify_printf(
1396
         "Reading group descriptors: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
1397
         block_group_number,
1398
         group_descriptor_offset,
1399
         group_descriptor_offset );
1400
      }
1401
#endif
1402
14.8k
      if( libbfio_handle_seek_offset(
1403
14.8k
           file_io_handle,
1404
14.8k
           group_descriptor_offset,
1405
14.8k
           SEEK_SET,
1406
14.8k
           error ) == -1 )
1407
0
      {
1408
0
        libcerror_error_set(
1409
0
         error,
1410
0
         LIBCERROR_ERROR_DOMAIN_IO,
1411
0
         LIBCERROR_IO_ERROR_SEEK_FAILED,
1412
0
         "%s: unable to seek group descriptors: %" PRIu32 " offset: %" PRIi64 " (0x%08" PRIx64 ").",
1413
0
         function,
1414
0
         block_group_number,
1415
0
         group_descriptor_offset,
1416
0
         group_descriptor_offset );
1417
1418
0
        goto on_error;
1419
0
      }
1420
14.8k
      is_primary_group_descriptor_table = 0;
1421
1422
14.8k
      if( number_of_blocks_per_meta_group == 0 )
1423
5.27k
      {
1424
5.27k
        first_group_number                = 0;
1425
5.27k
        number_of_group_descriptors       = internal_volume->superblock->number_of_block_groups;
1426
5.27k
        is_primary_group_descriptor_table = (uint8_t) ( block_group_number == 0 );
1427
5.27k
      }
1428
9.59k
      else if( block_group_number < metadata_block_group_start_block_number )
1429
688
      {
1430
688
        first_group_number                = 0;
1431
688
        number_of_group_descriptors       = metadata_block_group_start_block_number;
1432
688
        is_primary_group_descriptor_table = (uint8_t) ( block_group_number == 0 );
1433
688
      }
1434
8.90k
      else
1435
8.90k
      {
1436
8.90k
        first_group_number                = metadata_block_group_start_block_number + ( meta_group_number * number_of_blocks_per_meta_group );
1437
8.90k
        number_of_group_descriptors       = number_of_blocks_per_meta_group;
1438
8.90k
        is_primary_group_descriptor_table = (uint8_t) ( metadata_block_group_number == 0 );
1439
8.90k
      }
1440
14.8k
      for( group_descriptor_index = 0;
1441
5.41M
           group_descriptor_index < number_of_group_descriptors;
1442
5.39M
           group_descriptor_index++ )
1443
5.40M
      {
1444
5.40M
        if( libfsext_group_descriptor_initialize(
1445
5.40M
             &group_descriptor,
1446
5.40M
             error ) != 1 )
1447
0
        {
1448
0
          libcerror_error_set(
1449
0
           error,
1450
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1451
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1452
0
           "%s: unable to create group descriptor.",
1453
0
           function );
1454
1455
0
          goto on_error;
1456
0
        }
1457
5.40M
        group_descriptor->group_number = first_group_number + group_descriptor_index;
1458
1459
5.40M
        if( libfsext_group_descriptor_read_file_io_handle(
1460
5.40M
             group_descriptor,
1461
5.40M
             internal_volume->io_handle,
1462
5.40M
             file_io_handle,
1463
5.40M
             error ) != 1 )
1464
391
        {
1465
391
          libcerror_error_set(
1466
391
           error,
1467
391
           LIBCERROR_ERROR_DOMAIN_IO,
1468
391
           LIBCERROR_IO_ERROR_READ_FAILED,
1469
391
           "%s: unable to read group descriptor: %" PRIu32 ".",
1470
391
           function,
1471
391
           group_descriptor_index );
1472
1473
391
          goto on_error;
1474
391
        }
1475
5.39M
        if( is_primary_group_descriptor_table != 0 )
1476
1.71M
        {
1477
1.71M
          if( libcdata_array_append_entry(
1478
1.71M
               internal_volume->group_descriptors_array,
1479
1.71M
               &entry_index,
1480
1.71M
               (intptr_t *) group_descriptor,
1481
1.71M
               error ) != 1 )
1482
0
          {
1483
0
            libcerror_error_set(
1484
0
             error,
1485
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1486
0
             LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1487
0
             "%s: unable to append group descriptor: %" PRIu32 " to array.",
1488
0
             function,
1489
0
             group_descriptor_index );
1490
1491
0
            goto on_error;
1492
0
          }
1493
1.71M
          group_descriptor = NULL;
1494
1.71M
        }
1495
3.68M
        else
1496
3.68M
        {
1497
/* TODO compare group descriptors */
1498
3.68M
          if( libfsext_group_descriptor_free(
1499
3.68M
               &group_descriptor,
1500
3.68M
               error ) != 1 )
1501
0
          {
1502
0
            libcerror_error_set(
1503
0
             error,
1504
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1505
0
             LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1506
0
             "%s: unable to free group descriptor: %" PRIu32 ".",
1507
0
             function,
1508
0
             group_descriptor_index );
1509
1510
0
            goto on_error;
1511
0
          }
1512
3.68M
        }
1513
5.39M
      }
1514
14.4k
      if( metadata_block_group_number == ( number_of_blocks_per_meta_group - 1 ) )
1515
2.83k
      {
1516
2.83k
        meta_group_number += 1;
1517
2.83k
      }
1518
14.4k
    }
1519
#ifdef TODO
1520
/* TODO get group descriptor of block group */
1521
1522
    block_bitmap_offset  = group_descriptor->block_bitmap_block_number * internal_volume->io_handle->block_size;
1523
    inode_bitmap_offset  = group_descriptor->inode_bitmap_block_number * internal_volume->io_handle->block_size;
1524
1525
#if defined( HAVE_DEBUG_OUTPUT )
1526
    if( libcnotify_verbose != 0 )
1527
    {
1528
      libcnotify_printf(
1529
       "Reading block bitmap: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
1530
       block_group_number,
1531
       block_bitmap_offset,
1532
       block_bitmap_offset );
1533
    }
1534
#endif
1535
    if( libfsext_bitmap_initialize(
1536
         &bitmap,
1537
         error ) != 1 )
1538
    {
1539
      libcerror_error_set(
1540
       error,
1541
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1542
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1543
       "%s: unable to create bitmap.",
1544
       function );
1545
1546
      goto on_error;
1547
    }
1548
    if( libfsext_bitmap_read_file_io_handle(
1549
         bitmap,
1550
         internal_volume->io_handle,
1551
         file_io_handle,
1552
         block_bitmap_offset,
1553
         error ) != 1 )
1554
    {
1555
      libcerror_error_set(
1556
       error,
1557
       LIBCERROR_ERROR_DOMAIN_IO,
1558
       LIBCERROR_IO_ERROR_READ_FAILED,
1559
       "%s: unable to read block bitmap: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1560
       function,
1561
       block_group_number,
1562
       block_bitmap_offset,
1563
       block_bitmap_offset );
1564
1565
      goto on_error;
1566
    }
1567
    if( libfsext_bitmap_free(
1568
         &bitmap,
1569
         error ) != 1 )
1570
    {
1571
      libcerror_error_set(
1572
       error,
1573
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1574
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1575
       "%s: unable to free bitmap.",
1576
       function );
1577
1578
      goto on_error;
1579
    }
1580
#if defined( HAVE_DEBUG_OUTPUT )
1581
    if( libcnotify_verbose != 0 )
1582
    {
1583
      libcnotify_printf(
1584
       "Reading inode bitmap: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
1585
       block_group_number,
1586
       inode_bitmap_offset,
1587
       inode_bitmap_offset );
1588
    }
1589
#endif
1590
    if( libfsext_bitmap_initialize(
1591
         &bitmap,
1592
         error ) != 1 )
1593
    {
1594
      libcerror_error_set(
1595
       error,
1596
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1597
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1598
       "%s: unable to create bitmap.",
1599
       function );
1600
1601
      goto on_error;
1602
    }
1603
    if( libfsext_bitmap_read_file_io_handle(
1604
         bitmap,
1605
         internal_volume->io_handle,
1606
         file_io_handle,
1607
         inode_bitmap_offset,
1608
         error ) != 1 )
1609
    {
1610
      libcerror_error_set(
1611
       error,
1612
       LIBCERROR_ERROR_DOMAIN_IO,
1613
       LIBCERROR_IO_ERROR_READ_FAILED,
1614
       "%s: unable to read inode bitmap at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1615
       function,
1616
       inode_bitmap_offset,
1617
       inode_bitmap_offset );
1618
1619
      goto on_error;
1620
    }
1621
    if( libfsext_bitmap_free(
1622
         &bitmap,
1623
         error ) != 1 )
1624
    {
1625
      libcerror_error_set(
1626
       error,
1627
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1628
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1629
       "%s: unable to free bitmap.",
1630
       function );
1631
1632
      goto on_error;
1633
    }
1634
#endif /* TODO */
1635
1.58M
    block_group_offset += block_group_size;
1636
1637
1.58M
    block_group_number++;
1638
1.58M
  }
1639
1.58M
  while( block_group_number < number_of_block_groups );
1640
1641
4.12k
  return( 1 );
1642
1643
1.16k
on_error:
1644
1.16k
  if( bitmap != NULL )
1645
0
  {
1646
0
    libfsext_bitmap_free(
1647
0
     &bitmap,
1648
0
     NULL );
1649
0
  }
1650
1.16k
  if( group_descriptor != NULL )
1651
391
  {
1652
391
    libfsext_group_descriptor_free(
1653
391
     &group_descriptor,
1654
391
     NULL );
1655
391
  }
1656
1.16k
  if( superblock != NULL )
1657
777
  {
1658
777
    libfsext_superblock_free(
1659
777
     &superblock,
1660
777
     NULL );
1661
777
  }
1662
1.16k
  return( -1 );
1663
5.29k
}
1664
1665
/* Retrieves the format version
1666
 * Returns 1 if successful or -1 on error
1667
 */
1668
int libfsext_volume_get_format_version(
1669
     libfsext_volume_t *volume,
1670
     uint8_t *format_version,
1671
     libcerror_error_t **error )
1672
212
{
1673
212
  libfsext_internal_volume_t *internal_volume = NULL;
1674
212
  static char *function                       = "libfsext_volume_get_format_version";
1675
1676
212
  if( volume == NULL )
1677
0
  {
1678
0
    libcerror_error_set(
1679
0
     error,
1680
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1681
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1682
0
     "%s: invalid volume.",
1683
0
     function );
1684
1685
0
    return( -1 );
1686
0
  }
1687
212
  internal_volume = (libfsext_internal_volume_t *) volume;
1688
1689
212
  if( internal_volume->io_handle == NULL )
1690
0
  {
1691
0
    libcerror_error_set(
1692
0
     error,
1693
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1694
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1695
0
     "%s: invalid volume - missing IO handle.",
1696
0
     function );
1697
1698
0
    return( -1 );
1699
0
  }
1700
212
  if( format_version == NULL )
1701
0
  {
1702
0
    libcerror_error_set(
1703
0
     error,
1704
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1705
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1706
0
     "%s: invalid format version.",
1707
0
     function );
1708
1709
0
    return( -1 );
1710
0
  }
1711
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
1712
212
  if( libcthreads_read_write_lock_grab_for_read(
1713
212
       internal_volume->read_write_lock,
1714
212
       error ) != 1 )
1715
0
  {
1716
0
    libcerror_error_set(
1717
0
     error,
1718
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1719
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1720
0
     "%s: unable to grab read/write lock for reading.",
1721
0
     function );
1722
1723
0
    return( -1 );
1724
0
  }
1725
212
#endif
1726
212
  *format_version = internal_volume->io_handle->format_version;
1727
1728
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
1729
212
  if( libcthreads_read_write_lock_release_for_read(
1730
212
       internal_volume->read_write_lock,
1731
212
       error ) != 1 )
1732
0
  {
1733
0
    libcerror_error_set(
1734
0
     error,
1735
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1736
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1737
0
     "%s: unable to release read/write lock for reading.",
1738
0
     function );
1739
1740
0
    return( -1 );
1741
0
  }
1742
212
#endif
1743
212
  return( 1 );
1744
212
}
1745
1746
/* Retrieves the feature flags
1747
 * Returns 1 if successful or -1 on error
1748
 */
1749
int libfsext_volume_get_features_flags(
1750
     libfsext_volume_t *volume,
1751
     uint32_t *compatible_features_flags,
1752
     uint32_t *incompatible_features_flags,
1753
     uint32_t *read_only_compatible_features_flags,
1754
     libcerror_error_t **error )
1755
212
{
1756
212
  libfsext_internal_volume_t *internal_volume = NULL;
1757
212
  static char *function                       = "libfsext_volume_get_features_flags";
1758
1759
212
  if( volume == NULL )
1760
0
  {
1761
0
    libcerror_error_set(
1762
0
     error,
1763
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1764
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1765
0
     "%s: invalid volume.",
1766
0
     function );
1767
1768
0
    return( -1 );
1769
0
  }
1770
212
  internal_volume = (libfsext_internal_volume_t *) volume;
1771
1772
212
  if( internal_volume->superblock == NULL )
1773
0
  {
1774
0
    libcerror_error_set(
1775
0
     error,
1776
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1777
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1778
0
     "%s: invalid volume - missing superblock.",
1779
0
     function );
1780
1781
0
    return( -1 );
1782
0
  }
1783
212
  if( compatible_features_flags == NULL )
1784
0
  {
1785
0
    libcerror_error_set(
1786
0
     error,
1787
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1788
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1789
0
     "%s: invalid compatible features flags.",
1790
0
     function );
1791
1792
0
    return( -1 );
1793
0
  }
1794
212
  if( incompatible_features_flags == NULL )
1795
0
  {
1796
0
    libcerror_error_set(
1797
0
     error,
1798
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1799
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1800
0
     "%s: invalid incompatible features flags.",
1801
0
     function );
1802
1803
0
    return( -1 );
1804
0
  }
1805
212
  if( read_only_compatible_features_flags == NULL )
1806
0
  {
1807
0
    libcerror_error_set(
1808
0
     error,
1809
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1810
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1811
0
     "%s: invalid read-only compatible features flags.",
1812
0
     function );
1813
1814
0
    return( -1 );
1815
0
  }
1816
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
1817
212
  if( libcthreads_read_write_lock_grab_for_read(
1818
212
       internal_volume->read_write_lock,
1819
212
       error ) != 1 )
1820
0
  {
1821
0
    libcerror_error_set(
1822
0
     error,
1823
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1824
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1825
0
     "%s: unable to grab read/write lock for reading.",
1826
0
     function );
1827
1828
0
    return( -1 );
1829
0
  }
1830
212
#endif
1831
212
  *compatible_features_flags           = internal_volume->superblock->compatible_features_flags;
1832
212
  *incompatible_features_flags         = internal_volume->superblock->incompatible_features_flags;
1833
212
  *read_only_compatible_features_flags = internal_volume->superblock->read_only_compatible_features_flags;
1834
1835
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
1836
212
  if( libcthreads_read_write_lock_release_for_read(
1837
212
       internal_volume->read_write_lock,
1838
212
       error ) != 1 )
1839
0
  {
1840
0
    libcerror_error_set(
1841
0
     error,
1842
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1843
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1844
0
     "%s: unable to release read/write lock for reading.",
1845
0
     function );
1846
1847
0
    return( -1 );
1848
0
  }
1849
212
#endif
1850
212
  return( 1 );
1851
212
}
1852
1853
/* Retrieves the identifier
1854
 * The identifier is an UUID stored in big-endian and is 16 bytes of size
1855
 * Returns 1 if successful or -1 on error
1856
 */
1857
int libfsext_volume_get_identifier(
1858
     libfsext_volume_t *volume,
1859
     uint8_t *uuid_data,
1860
     size_t uuid_data_size,
1861
     libcerror_error_t **error )
1862
212
{
1863
212
  libfsext_internal_volume_t *internal_volume = NULL;
1864
212
  static char *function                       = "libfsext_volume_get_identifier";
1865
212
  int result                                  = 1;
1866
1867
212
  if( volume == NULL )
1868
0
  {
1869
0
    libcerror_error_set(
1870
0
     error,
1871
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1872
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1873
0
     "%s: invalid volume.",
1874
0
     function );
1875
1876
0
    return( -1 );
1877
0
  }
1878
212
  internal_volume = (libfsext_internal_volume_t *) volume;
1879
1880
212
  if( internal_volume->superblock == NULL )
1881
0
  {
1882
0
    libcerror_error_set(
1883
0
     error,
1884
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1885
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1886
0
     "%s: invalid volume - missing superblock.",
1887
0
     function );
1888
1889
0
    return( -1 );
1890
0
  }
1891
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1892
  if( libcthreads_read_write_lock_grab_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 grab read/write lock for reading.",
1901
     function );
1902
1903
    return( -1 );
1904
  }
1905
#endif
1906
212
  if( libfsext_superblock_get_file_system_identifier(
1907
212
       internal_volume->superblock,
1908
212
       uuid_data,
1909
212
       uuid_data_size,
1910
212
       error ) != 1 )
1911
0
  {
1912
0
    libcerror_error_set(
1913
0
     error,
1914
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1915
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1916
0
     "%s: unable to retrieve file system identifier.",
1917
0
     function );
1918
1919
0
    result = -1;
1920
0
  }
1921
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1922
  if( libcthreads_read_write_lock_release_for_read(
1923
       internal_volume->read_write_lock,
1924
       error ) != 1 )
1925
  {
1926
    libcerror_error_set(
1927
     error,
1928
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1929
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1930
     "%s: unable to release read/write lock for reading.",
1931
     function );
1932
1933
    return( -1 );
1934
  }
1935
#endif
1936
212
  return( result );
1937
212
}
1938
1939
/* Retrieves the size of the UTF-8 encoded label
1940
 * The returned size includes the end of string character
1941
 * Returns 1 if successful or -1 on error
1942
 */
1943
int libfsext_volume_get_utf8_label_size(
1944
     libfsext_volume_t *volume,
1945
     size_t *utf8_string_size,
1946
     libcerror_error_t **error )
1947
212
{
1948
212
  libfsext_internal_volume_t *internal_volume = NULL;
1949
212
  static char *function                       = "libfsext_volume_get_utf8_label_size";
1950
212
  size_t safe_utf8_string_size                = 1;
1951
212
  int result                                  = 1;
1952
1953
212
  if( volume == NULL )
1954
0
  {
1955
0
    libcerror_error_set(
1956
0
     error,
1957
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1958
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1959
0
     "%s: invalid volume.",
1960
0
     function );
1961
1962
0
    return( -1 );
1963
0
  }
1964
212
  internal_volume = (libfsext_internal_volume_t *) volume;
1965
1966
212
  if( utf8_string_size == NULL )
1967
0
  {
1968
0
    libcerror_error_set(
1969
0
     error,
1970
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1971
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1972
0
     "%s: invalid UTF-8 string size.",
1973
0
     function );
1974
1975
0
    return( -1 );
1976
0
  }
1977
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
1978
212
  if( libcthreads_read_write_lock_grab_for_read(
1979
212
       internal_volume->read_write_lock,
1980
212
       error ) != 1 )
1981
0
  {
1982
0
    libcerror_error_set(
1983
0
     error,
1984
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1985
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1986
0
     "%s: unable to grab read/write lock for reading.",
1987
0
     function );
1988
1989
0
    return( -1 );
1990
0
  }
1991
212
#endif
1992
212
  if( internal_volume->superblock != NULL )
1993
212
  {
1994
212
    if( libfsext_superblock_get_utf8_volume_label_size(
1995
212
         internal_volume->superblock,
1996
212
         &safe_utf8_string_size,
1997
212
         error ) != 1 )
1998
119
    {
1999
119
      libcerror_error_set(
2000
119
       error,
2001
119
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2002
119
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2003
119
       "%s: unable to retrieve UTF-8 volume label string size.",
2004
119
       function );
2005
2006
119
      result = -1;
2007
119
    }
2008
212
  }
2009
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2010
212
  if( libcthreads_read_write_lock_release_for_read(
2011
212
       internal_volume->read_write_lock,
2012
212
       error ) != 1 )
2013
0
  {
2014
0
    libcerror_error_set(
2015
0
     error,
2016
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2017
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2018
0
     "%s: unable to release read/write lock for reading.",
2019
0
     function );
2020
2021
0
    return( -1 );
2022
0
  }
2023
212
#endif
2024
212
  if( safe_utf8_string_size < 1 )
2025
49
  {
2026
49
    safe_utf8_string_size = 1;
2027
49
  }
2028
212
  *utf8_string_size = safe_utf8_string_size;
2029
2030
212
  return( result );
2031
212
}
2032
2033
/* Retrieves the UTF-8 encoded label
2034
 * The size should include the end of string character
2035
 * Returns 1 if successful or -1 on error
2036
 */
2037
int libfsext_volume_get_utf8_label(
2038
     libfsext_volume_t *volume,
2039
     uint8_t *utf8_string,
2040
     size_t utf8_string_size,
2041
     libcerror_error_t **error )
2042
212
{
2043
212
  libfsext_internal_volume_t *internal_volume = NULL;
2044
212
  static char *function                       = "libfsext_volume_get_utf8_label";
2045
212
  int result                                  = 1;
2046
2047
212
  if( volume == NULL )
2048
0
  {
2049
0
    libcerror_error_set(
2050
0
     error,
2051
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2052
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2053
0
     "%s: invalid volume.",
2054
0
     function );
2055
2056
0
    return( -1 );
2057
0
  }
2058
212
  internal_volume = (libfsext_internal_volume_t *) volume;
2059
2060
212
  if( utf8_string == NULL )
2061
0
  {
2062
0
    libcerror_error_set(
2063
0
     error,
2064
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2065
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2066
0
     "%s: invalid UTF-8 string.",
2067
0
     function );
2068
2069
0
    return( -1 );
2070
0
  }
2071
212
  if( utf8_string_size == 0 )
2072
0
  {
2073
0
    libcerror_error_set(
2074
0
     error,
2075
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2076
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2077
0
     "%s: invalid UTF-8 string size value too small.",
2078
0
     function );
2079
2080
0
    return( -1 );
2081
0
  }
2082
212
  if( utf8_string_size > (size_t) SSIZE_MAX )
2083
0
  {
2084
0
    libcerror_error_set(
2085
0
     error,
2086
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2087
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2088
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
2089
0
     function );
2090
2091
0
    return( -1 );
2092
0
  }
2093
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2094
212
  if( libcthreads_read_write_lock_grab_for_read(
2095
212
       internal_volume->read_write_lock,
2096
212
       error ) != 1 )
2097
0
  {
2098
0
    libcerror_error_set(
2099
0
     error,
2100
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2101
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2102
0
     "%s: unable to grab read/write lock for reading.",
2103
0
     function );
2104
2105
0
    return( -1 );
2106
0
  }
2107
212
#endif
2108
212
  if( internal_volume->superblock == NULL )
2109
0
  {
2110
0
    utf8_string[ 0 ] = 0;
2111
0
  }
2112
212
  else if( libfsext_superblock_get_utf8_volume_label(
2113
212
            internal_volume->superblock,
2114
212
            utf8_string,
2115
212
            utf8_string_size,
2116
212
            error ) != 1 )
2117
119
  {
2118
119
    libcerror_error_set(
2119
119
     error,
2120
119
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2121
119
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2122
119
     "%s: unable to retrieve UTF-8 volume label string.",
2123
119
     function );
2124
2125
119
    result = -1;
2126
119
  }
2127
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2128
212
  if( libcthreads_read_write_lock_release_for_read(
2129
212
       internal_volume->read_write_lock,
2130
212
       error ) != 1 )
2131
0
  {
2132
0
    libcerror_error_set(
2133
0
     error,
2134
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2135
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2136
0
     "%s: unable to release read/write lock for reading.",
2137
0
     function );
2138
2139
0
    return( -1 );
2140
0
  }
2141
212
#endif
2142
212
  return( result );
2143
212
}
2144
2145
/* Retrieves the size of the UTF-16 encoded label
2146
 * The returned size includes the end of string character
2147
 * Returns 1 if successful or -1 on error
2148
 */
2149
int libfsext_volume_get_utf16_label_size(
2150
     libfsext_volume_t *volume,
2151
     size_t *utf16_string_size,
2152
     libcerror_error_t **error )
2153
0
{
2154
0
  libfsext_internal_volume_t *internal_volume = NULL;
2155
0
  static char *function                       = "libfsext_volume_get_utf16_label_size";
2156
0
  size_t safe_utf16_string_size               = 1;
2157
0
  int result                                  = 1;
2158
2159
0
  if( volume == NULL )
2160
0
  {
2161
0
    libcerror_error_set(
2162
0
     error,
2163
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2164
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2165
0
     "%s: invalid volume.",
2166
0
     function );
2167
2168
0
    return( -1 );
2169
0
  }
2170
0
  internal_volume = (libfsext_internal_volume_t *) volume;
2171
2172
0
  if( utf16_string_size == NULL )
2173
0
  {
2174
0
    libcerror_error_set(
2175
0
     error,
2176
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2177
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2178
0
     "%s: invalid UTF-16 string size.",
2179
0
     function );
2180
2181
0
    return( -1 );
2182
0
  }
2183
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2184
0
  if( libcthreads_read_write_lock_grab_for_read(
2185
0
       internal_volume->read_write_lock,
2186
0
       error ) != 1 )
2187
0
  {
2188
0
    libcerror_error_set(
2189
0
     error,
2190
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2191
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2192
0
     "%s: unable to grab read/write lock for reading.",
2193
0
     function );
2194
2195
0
    return( -1 );
2196
0
  }
2197
0
#endif
2198
0
  if( internal_volume->superblock != NULL )
2199
0
  {
2200
0
    if( libfsext_superblock_get_utf16_volume_label_size(
2201
0
         internal_volume->superblock,
2202
0
         &safe_utf16_string_size,
2203
0
         error ) != 1 )
2204
0
    {
2205
0
      libcerror_error_set(
2206
0
       error,
2207
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2208
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2209
0
       "%s: unable to retrieve UTF-16 volume label string size.",
2210
0
       function );
2211
2212
0
      result = -1;
2213
0
    }
2214
0
  }
2215
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2216
0
  if( libcthreads_read_write_lock_release_for_read(
2217
0
       internal_volume->read_write_lock,
2218
0
       error ) != 1 )
2219
0
  {
2220
0
    libcerror_error_set(
2221
0
     error,
2222
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2223
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2224
0
     "%s: unable to release read/write lock for reading.",
2225
0
     function );
2226
2227
0
    return( -1 );
2228
0
  }
2229
0
#endif
2230
0
  if( safe_utf16_string_size < 1 )
2231
0
  {
2232
0
    safe_utf16_string_size = 1;
2233
0
  }
2234
0
  *utf16_string_size = safe_utf16_string_size;
2235
2236
0
  return( result );
2237
0
}
2238
2239
/* Retrieves the UTF-16 encoded label
2240
 * The size should include the end of string character
2241
 * Returns 1 if successful or -1 on error
2242
 */
2243
int libfsext_volume_get_utf16_label(
2244
     libfsext_volume_t *volume,
2245
     uint16_t *utf16_string,
2246
     size_t utf16_string_size,
2247
     libcerror_error_t **error )
2248
0
{
2249
0
  libfsext_internal_volume_t *internal_volume = NULL;
2250
0
  static char *function                       = "libfsext_volume_get_utf16_label";
2251
0
  int result                                  = 1;
2252
2253
0
  if( volume == NULL )
2254
0
  {
2255
0
    libcerror_error_set(
2256
0
     error,
2257
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2258
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2259
0
     "%s: invalid volume.",
2260
0
     function );
2261
2262
0
    return( -1 );
2263
0
  }
2264
0
  internal_volume = (libfsext_internal_volume_t *) volume;
2265
2266
0
  if( utf16_string == NULL )
2267
0
  {
2268
0
    libcerror_error_set(
2269
0
     error,
2270
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2271
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2272
0
     "%s: invalid UTF-16 string.",
2273
0
     function );
2274
2275
0
    return( -1 );
2276
0
  }
2277
0
  if( utf16_string_size == 0 )
2278
0
  {
2279
0
    libcerror_error_set(
2280
0
     error,
2281
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2282
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2283
0
     "%s: invalid UTF-16 string size value too small.",
2284
0
     function );
2285
2286
0
    return( -1 );
2287
0
  }
2288
0
  if( utf16_string_size > (size_t) SSIZE_MAX )
2289
0
  {
2290
0
    libcerror_error_set(
2291
0
     error,
2292
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2293
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2294
0
     "%s: invalid UTF-16 string size value exceeds maximum.",
2295
0
     function );
2296
2297
0
    return( -1 );
2298
0
  }
2299
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2300
0
  if( libcthreads_read_write_lock_grab_for_read(
2301
0
       internal_volume->read_write_lock,
2302
0
       error ) != 1 )
2303
0
  {
2304
0
    libcerror_error_set(
2305
0
     error,
2306
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2307
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2308
0
     "%s: unable to grab read/write lock for reading.",
2309
0
     function );
2310
2311
0
    return( -1 );
2312
0
  }
2313
0
#endif
2314
0
  if( internal_volume->superblock == NULL )
2315
0
  {
2316
0
    utf16_string[ 0 ] = 0;
2317
0
  }
2318
0
  else if( libfsext_superblock_get_utf16_volume_label(
2319
0
            internal_volume->superblock,
2320
0
            utf16_string,
2321
0
            utf16_string_size,
2322
0
            error ) != 1 )
2323
0
  {
2324
0
    libcerror_error_set(
2325
0
     error,
2326
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2327
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2328
0
     "%s: unable to retrieve UTF-16 volume label string.",
2329
0
     function );
2330
2331
0
    result = -1;
2332
0
  }
2333
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2334
0
  if( libcthreads_read_write_lock_release_for_read(
2335
0
       internal_volume->read_write_lock,
2336
0
       error ) != 1 )
2337
0
  {
2338
0
    libcerror_error_set(
2339
0
     error,
2340
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2341
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2342
0
     "%s: unable to release read/write lock for reading.",
2343
0
     function );
2344
2345
0
    return( -1 );
2346
0
  }
2347
0
#endif
2348
0
  return( result );
2349
0
}
2350
2351
/* Retrieves the size of the UTF-8 encoded last mount path
2352
 * The returned size includes the end of string character
2353
 * Returns 1 if successful or -1 on error
2354
 */
2355
int libfsext_volume_get_utf8_last_mount_path_size(
2356
     libfsext_volume_t *volume,
2357
     size_t *utf8_string_size,
2358
     libcerror_error_t **error )
2359
212
{
2360
212
  libfsext_internal_volume_t *internal_volume = NULL;
2361
212
  static char *function                       = "libfsext_volume_get_utf8_last_mount_path_size";
2362
212
  size_t safe_utf8_string_size                = 1;
2363
212
  int result                                  = 1;
2364
2365
212
  if( volume == NULL )
2366
0
  {
2367
0
    libcerror_error_set(
2368
0
     error,
2369
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2370
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2371
0
     "%s: invalid volume.",
2372
0
     function );
2373
2374
0
    return( -1 );
2375
0
  }
2376
212
  internal_volume = (libfsext_internal_volume_t *) volume;
2377
2378
212
  if( utf8_string_size == NULL )
2379
0
  {
2380
0
    libcerror_error_set(
2381
0
     error,
2382
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2383
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2384
0
     "%s: invalid UTF-8 string size.",
2385
0
     function );
2386
2387
0
    return( -1 );
2388
0
  }
2389
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2390
212
  if( libcthreads_read_write_lock_grab_for_read(
2391
212
       internal_volume->read_write_lock,
2392
212
       error ) != 1 )
2393
0
  {
2394
0
    libcerror_error_set(
2395
0
     error,
2396
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2397
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2398
0
     "%s: unable to grab read/write lock for reading.",
2399
0
     function );
2400
2401
0
    return( -1 );
2402
0
  }
2403
212
#endif
2404
212
  if( internal_volume->superblock != NULL )
2405
212
  {
2406
212
    if( libfsext_superblock_get_utf8_last_mount_path_size(
2407
212
         internal_volume->superblock,
2408
212
         &safe_utf8_string_size,
2409
212
         error ) != 1 )
2410
156
    {
2411
156
      libcerror_error_set(
2412
156
       error,
2413
156
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2414
156
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2415
156
       "%s: unable to retrieve UTF-8 volume last mount path string size.",
2416
156
       function );
2417
2418
156
      result = -1;
2419
156
    }
2420
212
  }
2421
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2422
212
  if( libcthreads_read_write_lock_release_for_read(
2423
212
       internal_volume->read_write_lock,
2424
212
       error ) != 1 )
2425
0
  {
2426
0
    libcerror_error_set(
2427
0
     error,
2428
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2429
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2430
0
     "%s: unable to release read/write lock for reading.",
2431
0
     function );
2432
2433
0
    return( -1 );
2434
0
  }
2435
212
#endif
2436
212
  if( result == 1 )
2437
56
  {
2438
56
    *utf8_string_size = safe_utf8_string_size;
2439
56
  }
2440
212
  return( result );
2441
212
}
2442
2443
/* Retrieves the UTF-8 encoded last mount path
2444
 * The size should include the end of string character
2445
 * Returns 1 if successful or -1 on error
2446
 */
2447
int libfsext_volume_get_utf8_last_mount_path(
2448
     libfsext_volume_t *volume,
2449
     uint8_t *utf8_string,
2450
     size_t utf8_string_size,
2451
     libcerror_error_t **error )
2452
212
{
2453
212
  libfsext_internal_volume_t *internal_volume = NULL;
2454
212
  static char *function                       = "libfsext_volume_get_utf8_last_mount_path";
2455
212
  int result                                  = 1;
2456
2457
212
  if( volume == NULL )
2458
0
  {
2459
0
    libcerror_error_set(
2460
0
     error,
2461
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2462
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2463
0
     "%s: invalid volume.",
2464
0
     function );
2465
2466
0
    return( -1 );
2467
0
  }
2468
212
  internal_volume = (libfsext_internal_volume_t *) volume;
2469
2470
212
  if( utf8_string == NULL )
2471
0
  {
2472
0
    libcerror_error_set(
2473
0
     error,
2474
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2475
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2476
0
     "%s: invalid UTF-8 string.",
2477
0
     function );
2478
2479
0
    return( -1 );
2480
0
  }
2481
212
  if( utf8_string_size == 0 )
2482
0
  {
2483
0
    libcerror_error_set(
2484
0
     error,
2485
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2486
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2487
0
     "%s: invalid UTF-8 string size value too small.",
2488
0
     function );
2489
2490
0
    return( -1 );
2491
0
  }
2492
212
  if( utf8_string_size > (size_t) SSIZE_MAX )
2493
0
  {
2494
0
    libcerror_error_set(
2495
0
     error,
2496
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2497
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2498
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
2499
0
     function );
2500
2501
0
    return( -1 );
2502
0
  }
2503
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2504
212
  if( libcthreads_read_write_lock_grab_for_read(
2505
212
       internal_volume->read_write_lock,
2506
212
       error ) != 1 )
2507
0
  {
2508
0
    libcerror_error_set(
2509
0
     error,
2510
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2511
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2512
0
     "%s: unable to grab read/write lock for reading.",
2513
0
     function );
2514
2515
0
    return( -1 );
2516
0
  }
2517
212
#endif
2518
212
  if( internal_volume->superblock == NULL )
2519
0
  {
2520
0
    utf8_string[ 0 ] = 0;
2521
0
  }
2522
212
  else if( libfsext_superblock_get_utf8_last_mount_path(
2523
212
            internal_volume->superblock,
2524
212
            utf8_string,
2525
212
            utf8_string_size,
2526
212
            error ) != 1 )
2527
166
  {
2528
166
    libcerror_error_set(
2529
166
     error,
2530
166
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2531
166
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2532
166
     "%s: unable to retrieve UTF-8 volume last mount path string.",
2533
166
     function );
2534
2535
166
    result = -1;
2536
166
  }
2537
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2538
212
  if( libcthreads_read_write_lock_release_for_read(
2539
212
       internal_volume->read_write_lock,
2540
212
       error ) != 1 )
2541
0
  {
2542
0
    libcerror_error_set(
2543
0
     error,
2544
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2545
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2546
0
     "%s: unable to release read/write lock for reading.",
2547
0
     function );
2548
2549
0
    return( -1 );
2550
0
  }
2551
212
#endif
2552
212
  return( result );
2553
212
}
2554
2555
/* Retrieves the size of the UTF-16 encoded last mount path
2556
 * The returned size includes the end of string character
2557
 * Returns 1 if successful or -1 on error
2558
 */
2559
int libfsext_volume_get_utf16_last_mount_path_size(
2560
     libfsext_volume_t *volume,
2561
     size_t *utf16_string_size,
2562
     libcerror_error_t **error )
2563
0
{
2564
0
  libfsext_internal_volume_t *internal_volume = NULL;
2565
0
  static char *function                       = "libfsext_volume_get_utf16_last_mount_path_size";
2566
0
  size_t safe_utf16_string_size               = 1;
2567
0
  int result                                  = 1;
2568
2569
0
  if( volume == NULL )
2570
0
  {
2571
0
    libcerror_error_set(
2572
0
     error,
2573
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2574
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2575
0
     "%s: invalid volume.",
2576
0
     function );
2577
2578
0
    return( -1 );
2579
0
  }
2580
0
  internal_volume = (libfsext_internal_volume_t *) volume;
2581
2582
0
  if( utf16_string_size == NULL )
2583
0
  {
2584
0
    libcerror_error_set(
2585
0
     error,
2586
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2587
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2588
0
     "%s: invalid UTF-16 string size.",
2589
0
     function );
2590
2591
0
    return( -1 );
2592
0
  }
2593
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2594
0
  if( libcthreads_read_write_lock_grab_for_read(
2595
0
       internal_volume->read_write_lock,
2596
0
       error ) != 1 )
2597
0
  {
2598
0
    libcerror_error_set(
2599
0
     error,
2600
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2601
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2602
0
     "%s: unable to grab read/write lock for reading.",
2603
0
     function );
2604
2605
0
    return( -1 );
2606
0
  }
2607
0
#endif
2608
0
  if( internal_volume->superblock != NULL )
2609
0
  {
2610
0
    if( libfsext_superblock_get_utf16_last_mount_path_size(
2611
0
         internal_volume->superblock,
2612
0
         &safe_utf16_string_size,
2613
0
         error ) != 1 )
2614
0
    {
2615
0
      libcerror_error_set(
2616
0
       error,
2617
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2618
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2619
0
       "%s: unable to retrieve UTF-16 volume last mount path string size.",
2620
0
       function );
2621
2622
0
      result = -1;
2623
0
    }
2624
0
  }
2625
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2626
0
  if( libcthreads_read_write_lock_release_for_read(
2627
0
       internal_volume->read_write_lock,
2628
0
       error ) != 1 )
2629
0
  {
2630
0
    libcerror_error_set(
2631
0
     error,
2632
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2633
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2634
0
     "%s: unable to release read/write lock for reading.",
2635
0
     function );
2636
2637
0
    return( -1 );
2638
0
  }
2639
0
#endif
2640
0
  if( result == 1 )
2641
0
  {
2642
0
    *utf16_string_size = safe_utf16_string_size;
2643
0
  }
2644
0
  return( result );
2645
0
}
2646
2647
/* Retrieves the UTF-16 encoded last mount path
2648
 * The size should include the end of string character
2649
 * Returns 1 if successful or -1 on error
2650
 */
2651
int libfsext_volume_get_utf16_last_mount_path(
2652
     libfsext_volume_t *volume,
2653
     uint16_t *utf16_string,
2654
     size_t utf16_string_size,
2655
     libcerror_error_t **error )
2656
0
{
2657
0
  libfsext_internal_volume_t *internal_volume = NULL;
2658
0
  static char *function                       = "libfsext_volume_get_utf16_last_mount_path";
2659
0
  int result                                  = 1;
2660
2661
0
  if( volume == NULL )
2662
0
  {
2663
0
    libcerror_error_set(
2664
0
     error,
2665
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2666
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2667
0
     "%s: invalid volume.",
2668
0
     function );
2669
2670
0
    return( -1 );
2671
0
  }
2672
0
  internal_volume = (libfsext_internal_volume_t *) volume;
2673
2674
0
  if( utf16_string == NULL )
2675
0
  {
2676
0
    libcerror_error_set(
2677
0
     error,
2678
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2679
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2680
0
     "%s: invalid UTF-16 string.",
2681
0
     function );
2682
2683
0
    return( -1 );
2684
0
  }
2685
0
  if( utf16_string_size == 0 )
2686
0
  {
2687
0
    libcerror_error_set(
2688
0
     error,
2689
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2690
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2691
0
     "%s: invalid UTF-16 string size value too small.",
2692
0
     function );
2693
2694
0
    return( -1 );
2695
0
  }
2696
0
  if( utf16_string_size > (size_t) SSIZE_MAX )
2697
0
  {
2698
0
    libcerror_error_set(
2699
0
     error,
2700
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2701
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2702
0
     "%s: invalid UTF-16 string size value exceeds maximum.",
2703
0
     function );
2704
2705
0
    return( -1 );
2706
0
  }
2707
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2708
0
  if( libcthreads_read_write_lock_grab_for_read(
2709
0
       internal_volume->read_write_lock,
2710
0
       error ) != 1 )
2711
0
  {
2712
0
    libcerror_error_set(
2713
0
     error,
2714
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2715
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2716
0
     "%s: unable to grab read/write lock for reading.",
2717
0
     function );
2718
2719
0
    return( -1 );
2720
0
  }
2721
0
#endif
2722
0
  if( internal_volume->superblock == NULL )
2723
0
  {
2724
0
    utf16_string[ 0 ] = 0;
2725
0
  }
2726
0
  else if( libfsext_superblock_get_utf16_last_mount_path(
2727
0
            internal_volume->superblock,
2728
0
            utf16_string,
2729
0
            utf16_string_size,
2730
0
            error ) != 1 )
2731
0
  {
2732
0
    libcerror_error_set(
2733
0
     error,
2734
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2735
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2736
0
     "%s: unable to retrieve UTF-16 volume last mount path string.",
2737
0
     function );
2738
2739
0
    result = -1;
2740
0
  }
2741
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2742
0
  if( libcthreads_read_write_lock_release_for_read(
2743
0
       internal_volume->read_write_lock,
2744
0
       error ) != 1 )
2745
0
  {
2746
0
    libcerror_error_set(
2747
0
     error,
2748
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2749
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2750
0
     "%s: unable to release read/write lock for reading.",
2751
0
     function );
2752
2753
0
    return( -1 );
2754
0
  }
2755
0
#endif
2756
0
  return( result );
2757
0
}
2758
2759
/* Retrieves the last mount time
2760
 * The timestamp is a signed 32-bit POSIX date and time value in number of seconds
2761
 * Returns 1 if successful or -1 on error
2762
 */
2763
int libfsext_volume_get_last_mount_time(
2764
     libfsext_volume_t *volume,
2765
     int32_t *posix_time,
2766
     libcerror_error_t **error )
2767
212
{
2768
212
  libfsext_internal_volume_t *internal_volume = NULL;
2769
212
  static char *function                       = "libfsext_volume_get_last_mount_time";
2770
2771
212
  if( volume == NULL )
2772
0
  {
2773
0
    libcerror_error_set(
2774
0
     error,
2775
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2776
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2777
0
     "%s: invalid volume.",
2778
0
     function );
2779
2780
0
    return( -1 );
2781
0
  }
2782
212
  internal_volume = (libfsext_internal_volume_t *) volume;
2783
2784
212
  if( internal_volume->superblock == NULL )
2785
0
  {
2786
0
    libcerror_error_set(
2787
0
     error,
2788
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2789
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2790
0
     "%s: invalid volume - missing superblock.",
2791
0
     function );
2792
2793
0
    return( -1 );
2794
0
  }
2795
212
  if( posix_time == NULL )
2796
0
  {
2797
0
    libcerror_error_set(
2798
0
     error,
2799
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2800
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2801
0
     "%s: invalid posix time.",
2802
0
     function );
2803
2804
0
    return( -1 );
2805
0
  }
2806
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2807
212
  if( libcthreads_read_write_lock_grab_for_read(
2808
212
       internal_volume->read_write_lock,
2809
212
       error ) != 1 )
2810
0
  {
2811
0
    libcerror_error_set(
2812
0
     error,
2813
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2814
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2815
0
     "%s: unable to grab read/write lock for reading.",
2816
0
     function );
2817
2818
0
    return( -1 );
2819
0
  }
2820
212
#endif
2821
212
  *posix_time = (int32_t) internal_volume->superblock->last_mount_time;
2822
2823
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2824
212
  if( libcthreads_read_write_lock_release_for_read(
2825
212
       internal_volume->read_write_lock,
2826
212
       error ) != 1 )
2827
0
  {
2828
0
    libcerror_error_set(
2829
0
     error,
2830
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2831
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2832
0
     "%s: unable to release read/write lock for reading.",
2833
0
     function );
2834
2835
0
    return( -1 );
2836
0
  }
2837
212
#endif
2838
212
  return( 1 );
2839
212
}
2840
2841
/* Retrieves the last written time
2842
 * The timestamp is a signed 32-bit POSIX date and time value in number of seconds
2843
 * Returns 1 if successful or -1 on error
2844
 */
2845
int libfsext_volume_get_last_written_time(
2846
     libfsext_volume_t *volume,
2847
     int32_t *posix_time,
2848
     libcerror_error_t **error )
2849
212
{
2850
212
  libfsext_internal_volume_t *internal_volume = NULL;
2851
212
  static char *function                       = "libfsext_volume_get_last_mount_time";
2852
2853
212
  if( volume == NULL )
2854
0
  {
2855
0
    libcerror_error_set(
2856
0
     error,
2857
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2858
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2859
0
     "%s: invalid volume.",
2860
0
     function );
2861
2862
0
    return( -1 );
2863
0
  }
2864
212
  internal_volume = (libfsext_internal_volume_t *) volume;
2865
2866
212
  if( internal_volume->superblock == NULL )
2867
0
  {
2868
0
    libcerror_error_set(
2869
0
     error,
2870
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2871
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2872
0
     "%s: invalid volume - missing superblock.",
2873
0
     function );
2874
2875
0
    return( -1 );
2876
0
  }
2877
212
  if( posix_time == NULL )
2878
0
  {
2879
0
    libcerror_error_set(
2880
0
     error,
2881
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2882
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2883
0
     "%s: invalid posix time.",
2884
0
     function );
2885
2886
0
    return( -1 );
2887
0
  }
2888
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2889
212
  if( libcthreads_read_write_lock_grab_for_read(
2890
212
       internal_volume->read_write_lock,
2891
212
       error ) != 1 )
2892
0
  {
2893
0
    libcerror_error_set(
2894
0
     error,
2895
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2896
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2897
0
     "%s: unable to grab read/write lock for reading.",
2898
0
     function );
2899
2900
0
    return( -1 );
2901
0
  }
2902
212
#endif
2903
212
  *posix_time = (int32_t) internal_volume->superblock->last_written_time;
2904
2905
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
2906
212
  if( libcthreads_read_write_lock_release_for_read(
2907
212
       internal_volume->read_write_lock,
2908
212
       error ) != 1 )
2909
0
  {
2910
0
    libcerror_error_set(
2911
0
     error,
2912
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2913
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2914
0
     "%s: unable to release read/write lock for reading.",
2915
0
     function );
2916
2917
0
    return( -1 );
2918
0
  }
2919
212
#endif
2920
212
  return( 1 );
2921
212
}
2922
2923
/* Retrieves the root directory file entry
2924
 * Returns 1 if successful, 0 if not available or -1 on error
2925
 */
2926
int libfsext_internal_volume_get_root_directory(
2927
     libfsext_internal_volume_t *internal_volume,
2928
     libfsext_file_entry_t **file_entry,
2929
     libcerror_error_t **error )
2930
1.68k
{
2931
1.68k
  libfsext_inode_t *inode      = NULL;
2932
1.68k
  libfsext_inode_t *safe_inode = NULL;
2933
1.68k
  static char *function        = "libfsext_internal_volume_get_root_directory";
2934
2935
1.68k
  if( internal_volume == NULL )
2936
0
  {
2937
0
    libcerror_error_set(
2938
0
     error,
2939
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2940
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2941
0
     "%s: invalid volume.",
2942
0
     function );
2943
2944
0
    return( -1 );
2945
0
  }
2946
1.68k
  if( internal_volume->superblock == NULL )
2947
0
  {
2948
0
    libcerror_error_set(
2949
0
     error,
2950
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2951
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2952
0
     "%s: invalid volume - missing superblock.",
2953
0
     function );
2954
2955
0
    return( -1 );
2956
0
  }
2957
1.68k
  if( file_entry == NULL )
2958
0
  {
2959
0
    libcerror_error_set(
2960
0
     error,
2961
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2962
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2963
0
     "%s: invalid file entry.",
2964
0
     function );
2965
2966
0
    return( -1 );
2967
0
  }
2968
1.68k
  if( *file_entry != NULL )
2969
0
  {
2970
0
    libcerror_error_set(
2971
0
     error,
2972
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2973
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2974
0
     "%s: invalid file entry value already set.",
2975
0
     function );
2976
2977
0
    return( -1 );
2978
0
  }
2979
1.68k
  if( internal_volume->superblock->number_of_inodes < LIBFSEXT_INODE_NUMBER_ROOT_DIRECTORY )
2980
7
  {
2981
7
    return( 0 );
2982
7
  }
2983
1.68k
  if( libfsext_inode_table_get_inode_by_number(
2984
1.68k
       internal_volume->inode_table,
2985
1.68k
       internal_volume->file_io_handle,
2986
1.68k
       LIBFSEXT_INODE_NUMBER_ROOT_DIRECTORY,
2987
1.68k
       &inode,
2988
1.68k
       error ) != 1 )
2989
578
  {
2990
578
    libcerror_error_set(
2991
578
     error,
2992
578
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2993
578
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2994
578
     "%s: unable to retrieve inode: %d.",
2995
578
     function,
2996
578
     LIBFSEXT_INODE_NUMBER_ROOT_DIRECTORY );
2997
2998
578
    goto on_error;
2999
578
  }
3000
1.10k
  if( inode == NULL )
3001
0
  {
3002
0
    libcerror_error_set(
3003
0
     error,
3004
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3005
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3006
0
     "%s: missing inode: %d.",
3007
0
     function,
3008
0
     LIBFSEXT_INODE_NUMBER_ROOT_DIRECTORY );
3009
3010
0
    goto on_error;
3011
0
  }
3012
1.10k
  if( libfsext_inode_clone(
3013
1.10k
       &safe_inode,
3014
1.10k
       inode,
3015
1.10k
       error ) != 1 )
3016
0
  {
3017
0
    libcerror_error_set(
3018
0
     error,
3019
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3020
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3021
0
     "%s: unable to create inode.",
3022
0
     function );
3023
3024
0
    goto on_error;
3025
0
  }
3026
  /* libfsext_file_entry_initialize takes over management of inode
3027
   */
3028
1.10k
  if( libfsext_file_entry_initialize(
3029
1.10k
       file_entry,
3030
1.10k
       internal_volume->io_handle,
3031
1.10k
       internal_volume->file_io_handle,
3032
1.10k
       internal_volume->inode_table,
3033
1.10k
       LIBFSEXT_INODE_NUMBER_ROOT_DIRECTORY,
3034
1.10k
       safe_inode,
3035
1.10k
       NULL,
3036
1.10k
       error ) != 1 )
3037
56
  {
3038
56
    libcerror_error_set(
3039
56
     error,
3040
56
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3041
56
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3042
56
     "%s: unable to create file entry.",
3043
56
     function );
3044
3045
56
    goto on_error;
3046
56
  }
3047
1.04k
  return( 1 );
3048
3049
634
on_error:
3050
634
  if( safe_inode != NULL )
3051
56
  {
3052
56
    libfsext_inode_free(
3053
56
     &safe_inode,
3054
56
     NULL );
3055
56
  }
3056
634
  return( -1 );
3057
1.10k
}
3058
3059
/* Retrieves the root directory file entry
3060
 * Returns 1 if successful, 0 if not available or -1 on error
3061
 */
3062
int libfsext_volume_get_root_directory(
3063
     libfsext_volume_t *volume,
3064
     libfsext_file_entry_t **file_entry,
3065
     libcerror_error_t **error )
3066
1.68k
{
3067
1.68k
  libfsext_internal_volume_t *internal_volume = NULL;
3068
1.68k
  static char *function                       = "libfsext_volume_get_root_directory";
3069
1.68k
  int result                                  = 0;
3070
3071
1.68k
  if( volume == NULL )
3072
0
  {
3073
0
    libcerror_error_set(
3074
0
     error,
3075
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3076
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3077
0
     "%s: invalid volume.",
3078
0
     function );
3079
3080
0
    return( -1 );
3081
0
  }
3082
1.68k
  internal_volume = (libfsext_internal_volume_t *) volume;
3083
3084
1.68k
  if( file_entry == NULL )
3085
0
  {
3086
0
    libcerror_error_set(
3087
0
     error,
3088
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3089
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3090
0
     "%s: invalid file entry.",
3091
0
     function );
3092
3093
0
    return( -1 );
3094
0
  }
3095
1.68k
  if( *file_entry != NULL )
3096
0
  {
3097
0
    libcerror_error_set(
3098
0
     error,
3099
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3100
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3101
0
     "%s: invalid file entry value already set.",
3102
0
     function );
3103
3104
0
    return( -1 );
3105
0
  }
3106
1.68k
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
3107
1.68k
  if( libcthreads_read_write_lock_grab_for_write(
3108
1.68k
       internal_volume->read_write_lock,
3109
1.68k
       error ) != 1 )
3110
0
  {
3111
0
    libcerror_error_set(
3112
0
     error,
3113
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3114
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3115
0
     "%s: unable to grab read/write lock for writing.",
3116
0
     function );
3117
3118
0
    return( -1 );
3119
0
  }
3120
1.68k
#endif
3121
1.68k
  result = libfsext_internal_volume_get_root_directory(
3122
1.68k
            internal_volume,
3123
1.68k
            file_entry,
3124
1.68k
            error );
3125
3126
1.68k
  if( result == -1 )
3127
634
  {
3128
634
    libcerror_error_set(
3129
634
     error,
3130
634
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3131
634
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3132
634
     "%s: unable to retrieve root directory.",
3133
634
     function );
3134
3135
634
    result = -1;
3136
634
  }
3137
1.68k
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
3138
1.68k
  if( libcthreads_read_write_lock_release_for_write(
3139
1.68k
       internal_volume->read_write_lock,
3140
1.68k
       error ) != 1 )
3141
0
  {
3142
0
    libcerror_error_set(
3143
0
     error,
3144
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3145
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3146
0
     "%s: unable to release read/write lock for writing.",
3147
0
     function );
3148
3149
0
    libfsext_file_entry_free(
3150
0
     file_entry,
3151
0
     NULL );
3152
3153
0
    return( -1 );
3154
0
  }
3155
1.68k
#endif
3156
1.68k
  return( result );
3157
1.68k
}
3158
3159
/* Retrieves the number of file entries (inodes)
3160
 * Returns 1 if successful or -1 on error
3161
 */
3162
int libfsext_volume_get_number_of_file_entries(
3163
     libfsext_volume_t *volume,
3164
     uint32_t *number_of_file_entries,
3165
     libcerror_error_t **error )
3166
212
{
3167
212
  libfsext_internal_volume_t *internal_volume = NULL;
3168
212
  static char *function                       = "libfsext_volume_get_number_of_file_entries";
3169
3170
212
  if( volume == NULL )
3171
0
  {
3172
0
    libcerror_error_set(
3173
0
     error,
3174
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3175
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3176
0
     "%s: invalid volume.",
3177
0
     function );
3178
3179
0
    return( -1 );
3180
0
  }
3181
212
  internal_volume = (libfsext_internal_volume_t *) volume;
3182
3183
212
  if( internal_volume->superblock == NULL )
3184
0
  {
3185
0
    libcerror_error_set(
3186
0
     error,
3187
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3188
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3189
0
     "%s: invalid volume - missing superblock.",
3190
0
     function );
3191
3192
0
    return( -1 );
3193
0
  }
3194
212
  if( number_of_file_entries == NULL )
3195
0
  {
3196
0
    libcerror_error_set(
3197
0
     error,
3198
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3199
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3200
0
     "%s: invalid number of file entries.",
3201
0
     function );
3202
3203
0
    return( -1 );
3204
0
  }
3205
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
3206
212
  if( libcthreads_read_write_lock_grab_for_read(
3207
212
       internal_volume->read_write_lock,
3208
212
       error ) != 1 )
3209
0
  {
3210
0
    libcerror_error_set(
3211
0
     error,
3212
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3213
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3214
0
     "%s: unable to grab read/write lock for reading.",
3215
0
     function );
3216
3217
0
    return( -1 );
3218
0
  }
3219
212
#endif
3220
212
  *number_of_file_entries = internal_volume->superblock->number_of_inodes;
3221
3222
212
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
3223
212
  if( libcthreads_read_write_lock_release_for_read(
3224
212
       internal_volume->read_write_lock,
3225
212
       error ) != 1 )
3226
0
  {
3227
0
    libcerror_error_set(
3228
0
     error,
3229
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3230
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3231
0
     "%s: unable to release read/write lock for reading.",
3232
0
     function );
3233
3234
0
    return( -1 );
3235
0
  }
3236
212
#endif
3237
212
  return( 1 );
3238
212
}
3239
3240
/* Retrieves the file entry of a specific inode
3241
 * Returns 1 if successful or -1 on error
3242
 */
3243
int libfsext_internal_volume_get_file_entry_by_inode(
3244
     libfsext_internal_volume_t *internal_volume,
3245
     uint32_t inode_number,
3246
     libfsext_file_entry_t **file_entry,
3247
     libcerror_error_t **error )
3248
0
{
3249
0
  libfsext_inode_t *inode      = NULL;
3250
0
  libfsext_inode_t *safe_inode = NULL;
3251
0
  static char *function        = "libfsext_internal_volume_get_file_entry_by_inode";
3252
3253
0
  if( internal_volume == NULL )
3254
0
  {
3255
0
    libcerror_error_set(
3256
0
     error,
3257
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3258
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3259
0
     "%s: invalid volume.",
3260
0
     function );
3261
3262
0
    return( -1 );
3263
0
  }
3264
0
  if( file_entry == NULL )
3265
0
  {
3266
0
    libcerror_error_set(
3267
0
     error,
3268
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3269
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3270
0
     "%s: invalid file entry.",
3271
0
     function );
3272
3273
0
    return( -1 );
3274
0
  }
3275
0
  if( *file_entry != NULL )
3276
0
  {
3277
0
    libcerror_error_set(
3278
0
     error,
3279
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3280
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3281
0
     "%s: invalid file entry value already set.",
3282
0
     function );
3283
3284
0
    return( -1 );
3285
0
  }
3286
0
  if( libfsext_inode_table_get_inode_by_number(
3287
0
       internal_volume->inode_table,
3288
0
       internal_volume->file_io_handle,
3289
0
       inode_number,
3290
0
       &inode,
3291
0
       error ) != 1 )
3292
0
  {
3293
0
    libcerror_error_set(
3294
0
     error,
3295
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3296
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3297
0
     "%s: unable to retrieve inode: %" PRIu32 ".",
3298
0
     function,
3299
0
     inode_number );
3300
3301
0
    goto on_error;
3302
0
  }
3303
0
  if( inode == NULL )
3304
0
  {
3305
0
    libcerror_error_set(
3306
0
     error,
3307
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3308
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3309
0
     "%s: missing inode: %" PRIu32 ".",
3310
0
     function,
3311
0
     inode_number );
3312
3313
0
    goto on_error;
3314
0
  }
3315
0
  if( libfsext_inode_clone(
3316
0
       &safe_inode,
3317
0
       inode,
3318
0
       error ) != 1 )
3319
0
  {
3320
0
    libcerror_error_set(
3321
0
     error,
3322
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3323
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3324
0
     "%s: unable to create inode.",
3325
0
     function );
3326
3327
0
    goto on_error;
3328
0
  }
3329
  /* libfsext_file_entry_initialize takes over management of safe_inode
3330
   */
3331
0
  if( libfsext_file_entry_initialize(
3332
0
       file_entry,
3333
0
       internal_volume->io_handle,
3334
0
       internal_volume->file_io_handle,
3335
0
       internal_volume->inode_table,
3336
0
       inode_number,
3337
0
       safe_inode,
3338
0
       NULL,
3339
0
       error ) != 1 )
3340
0
  {
3341
0
    libcerror_error_set(
3342
0
     error,
3343
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3344
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3345
0
     "%s: unable to create file entry.",
3346
0
     function );
3347
3348
0
    goto on_error;
3349
0
  }
3350
0
  return( 1 );
3351
3352
0
on_error:
3353
0
  if( safe_inode != NULL )
3354
0
  {
3355
0
    libfsext_inode_free(
3356
0
     &safe_inode,
3357
0
     NULL );
3358
0
  }
3359
0
  return( -1 );
3360
0
}
3361
3362
/* Retrieves the file entry of a specific inode
3363
 * Returns 1 if successful or -1 on error
3364
 */
3365
int libfsext_volume_get_file_entry_by_inode(
3366
     libfsext_volume_t *volume,
3367
     uint32_t inode_number,
3368
     libfsext_file_entry_t **file_entry,
3369
     libcerror_error_t **error )
3370
0
{
3371
0
  libfsext_internal_volume_t *internal_volume = NULL;
3372
0
  static char *function                       = "libfsext_volume_get_file_entry_by_inode";
3373
0
  int result                                  = 1;
3374
3375
0
  if( volume == NULL )
3376
0
  {
3377
0
    libcerror_error_set(
3378
0
     error,
3379
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3380
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3381
0
     "%s: invalid volume.",
3382
0
     function );
3383
3384
0
    return( -1 );
3385
0
  }
3386
0
  internal_volume = (libfsext_internal_volume_t *) volume;
3387
3388
0
  if( file_entry == NULL )
3389
0
  {
3390
0
    libcerror_error_set(
3391
0
     error,
3392
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3393
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3394
0
     "%s: invalid file entry.",
3395
0
     function );
3396
3397
0
    return( -1 );
3398
0
  }
3399
0
  if( *file_entry != NULL )
3400
0
  {
3401
0
    libcerror_error_set(
3402
0
     error,
3403
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3404
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3405
0
     "%s: invalid file entry value already set.",
3406
0
     function );
3407
3408
0
    return( -1 );
3409
0
  }
3410
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
3411
0
  if( libcthreads_read_write_lock_grab_for_write(
3412
0
       internal_volume->read_write_lock,
3413
0
       error ) != 1 )
3414
0
  {
3415
0
    libcerror_error_set(
3416
0
     error,
3417
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3418
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3419
0
     "%s: unable to grab read/write lock for writing.",
3420
0
     function );
3421
3422
0
    return( -1 );
3423
0
  }
3424
0
#endif
3425
0
  if( libfsext_internal_volume_get_file_entry_by_inode(
3426
0
       internal_volume,
3427
0
       inode_number,
3428
0
       file_entry,
3429
0
       error ) != 1 )
3430
0
  {
3431
0
    libcerror_error_set(
3432
0
     error,
3433
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3434
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3435
0
     "%s: unable to retrieve inode: %" PRIu32 ".",
3436
0
     function,
3437
0
     inode_number );
3438
3439
0
    result = -1;
3440
0
  }
3441
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
3442
0
  if( libcthreads_read_write_lock_release_for_write(
3443
0
       internal_volume->read_write_lock,
3444
0
       error ) != 1 )
3445
0
  {
3446
0
    libcerror_error_set(
3447
0
     error,
3448
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3449
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3450
0
     "%s: unable to release read/write lock for writing.",
3451
0
     function );
3452
3453
0
    libfsext_file_entry_free(
3454
0
     file_entry,
3455
0
     NULL );
3456
3457
0
    return( -1 );
3458
0
  }
3459
0
#endif
3460
0
  return( result );
3461
0
}
3462
3463
/* Retrieves the file entry for an UTF-8 encoded path
3464
 * Returns 1 if successful, 0 if no such file entry or -1 on error
3465
 */
3466
int libfsext_internal_volume_get_file_entry_by_utf8_path(
3467
     libfsext_internal_volume_t *internal_volume,
3468
     const uint8_t *utf8_string,
3469
     size_t utf8_string_length,
3470
     libfsext_file_entry_t **file_entry,
3471
     libcerror_error_t **error )
3472
1.80k
{
3473
1.80k
  libfsext_directory_t *directory                  = NULL;
3474
1.80k
  libfsext_directory_entry_t *directory_entry      = NULL;
3475
1.80k
  libfsext_directory_entry_t *safe_directory_entry = NULL;
3476
1.80k
  libfsext_inode_t *inode                          = NULL;
3477
1.80k
  libfsext_inode_t *safe_inode                     = NULL;
3478
1.80k
  const uint8_t *utf8_string_segment               = NULL;
3479
1.80k
  static char *function                            = "libfsext_internal_volume_get_file_entry_by_utf8_path";
3480
1.80k
  libuna_unicode_character_t unicode_character     = 0;
3481
1.80k
  size_t utf8_string_index                         = 0;
3482
1.80k
  size_t utf8_string_segment_length                = 0;
3483
1.80k
  uint32_t inode_number                            = 0;
3484
1.80k
  int result                                       = 0;
3485
3486
1.80k
  if( internal_volume == NULL )
3487
0
  {
3488
0
    libcerror_error_set(
3489
0
     error,
3490
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3491
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3492
0
     "%s: invalid volume.",
3493
0
     function );
3494
3495
0
    return( -1 );
3496
0
  }
3497
1.80k
  if( utf8_string == NULL )
3498
0
  {
3499
0
    libcerror_error_set(
3500
0
     error,
3501
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3502
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3503
0
     "%s: invalid UTF-8 string.",
3504
0
     function );
3505
3506
0
    return( -1 );
3507
0
  }
3508
1.80k
  if( utf8_string_length > (size_t) SSIZE_MAX )
3509
0
  {
3510
0
    libcerror_error_set(
3511
0
     error,
3512
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3513
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
3514
0
     "%s: invalid UTF-8 string length value exceeds maximum.",
3515
0
     function );
3516
3517
0
    return( -1 );
3518
0
  }
3519
1.80k
  if( file_entry == NULL )
3520
0
  {
3521
0
    libcerror_error_set(
3522
0
     error,
3523
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3524
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3525
0
     "%s: invalid file entry.",
3526
0
     function );
3527
3528
0
    return( -1 );
3529
0
  }
3530
1.80k
  if( *file_entry != NULL )
3531
0
  {
3532
0
    libcerror_error_set(
3533
0
     error,
3534
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3535
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3536
0
     "%s: invalid file entry value already set.",
3537
0
     function );
3538
3539
0
    return( -1 );
3540
0
  }
3541
1.80k
  if( utf8_string_length > 0 )
3542
1.80k
  {
3543
    /* Ignore a leading separator
3544
     */
3545
1.80k
    if( utf8_string[ utf8_string_index ] == (uint8_t) LIBFSEXT_SEPARATOR )
3546
1.80k
    {
3547
1.80k
      utf8_string_index++;
3548
1.80k
    }
3549
1.80k
  }
3550
1.80k
  inode_number = LIBFSEXT_INODE_NUMBER_ROOT_DIRECTORY;
3551
3552
1.80k
  if( libfsext_inode_table_get_inode_by_number(
3553
1.80k
       internal_volume->inode_table,
3554
1.80k
       internal_volume->file_io_handle,
3555
1.80k
       inode_number,
3556
1.80k
       &inode,
3557
1.80k
       error ) != 1 )
3558
717
  {
3559
717
    libcerror_error_set(
3560
717
     error,
3561
717
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3562
717
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3563
717
     "%s: unable to retrieve inode: %" PRIu32 ".",
3564
717
     function,
3565
717
     inode_number );
3566
3567
717
    goto on_error;
3568
717
  }
3569
1.08k
  if( ( utf8_string_length == 0 )
3570
1.08k
   || ( utf8_string_length == 1 ) )
3571
0
  {
3572
0
    result = 1;
3573
0
  }
3574
1.82k
  else while( utf8_string_index < utf8_string_length )
3575
1.52k
  {
3576
1.52k
    if( directory != NULL )
3577
439
    {
3578
439
      if( libfsext_directory_free(
3579
439
           &directory,
3580
439
           error ) != 1 )
3581
0
      {
3582
0
        libcerror_error_set(
3583
0
         error,
3584
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3585
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3586
0
         "%s: unable to free directory.",
3587
0
         function );
3588
3589
0
        goto on_error;
3590
0
      }
3591
439
    }
3592
1.52k
    if( libfsext_directory_initialize(
3593
1.52k
         &directory,
3594
1.52k
         error ) != 1 )
3595
0
    {
3596
0
      libcerror_error_set(
3597
0
       error,
3598
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3599
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3600
0
       "%s: unable to create directory.",
3601
0
       function );
3602
3603
0
      goto on_error;
3604
0
    }
3605
1.52k
    if( libfsext_directory_read_file_io_handle(
3606
1.52k
         directory,
3607
1.52k
         internal_volume->io_handle,
3608
1.52k
         internal_volume->file_io_handle,
3609
1.52k
         inode,
3610
1.52k
         error ) != 1 )
3611
360
    {
3612
360
      libcerror_error_set(
3613
360
       error,
3614
360
       LIBCERROR_ERROR_DOMAIN_IO,
3615
360
       LIBCERROR_IO_ERROR_READ_FAILED,
3616
360
       "%s: unable to read directory from inode: %" PRIu32 ".",
3617
360
       function,
3618
360
       inode_number );
3619
3620
360
      goto on_error;
3621
360
    }
3622
1.16k
    utf8_string_segment        = &( utf8_string[ utf8_string_index ] );
3623
1.16k
    utf8_string_segment_length = utf8_string_index;
3624
3625
12.0k
    while( utf8_string_index < utf8_string_length )
3626
11.6k
    {
3627
11.6k
      if( libuna_unicode_character_copy_from_utf8(
3628
11.6k
           &unicode_character,
3629
11.6k
           utf8_string,
3630
11.6k
           utf8_string_length,
3631
11.6k
           &utf8_string_index,
3632
11.6k
           error ) != 1 )
3633
0
      {
3634
0
        libcerror_error_set(
3635
0
         error,
3636
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3637
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
3638
0
         "%s: unable to copy UTF-8 string to Unicode character.",
3639
0
         function );
3640
3641
0
        goto on_error;
3642
0
      }
3643
11.6k
      if( ( unicode_character == (libuna_unicode_character_t) LIBFSEXT_SEPARATOR )
3644
10.8k
       || ( unicode_character == 0 ) )
3645
776
      {
3646
776
        utf8_string_segment_length += 1;
3647
3648
776
        break;
3649
776
      }
3650
11.6k
    }
3651
1.16k
    utf8_string_segment_length = utf8_string_index - utf8_string_segment_length;
3652
3653
1.16k
    if( utf8_string_segment_length == 0 )
3654
0
    {
3655
0
      result = 0;
3656
0
    }
3657
1.16k
    else
3658
1.16k
    {
3659
1.16k
      result = libfsext_directory_get_entry_by_utf8_name(
3660
1.16k
                directory,
3661
1.16k
                utf8_string_segment,
3662
1.16k
                utf8_string_segment_length,
3663
1.16k
                &directory_entry,
3664
1.16k
                error );
3665
1.16k
    }
3666
1.16k
    if( result == -1 )
3667
61
    {
3668
61
      libcerror_error_set(
3669
61
       error,
3670
61
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3671
61
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3672
61
       "%s: unable to retrieve directory entry by UTF-8 name.",
3673
61
       function );
3674
3675
61
      goto on_error;
3676
61
    }
3677
1.10k
    else if( result == 0 )
3678
122
    {
3679
122
      break;
3680
122
    }
3681
979
    if( libfsext_directory_entry_get_inode_number(
3682
979
         directory_entry,
3683
979
         &inode_number,
3684
979
         error ) != 1 )
3685
0
    {
3686
0
      libcerror_error_set(
3687
0
       error,
3688
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3689
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3690
0
       "%s: unable to retrieve inode number from directory entry.",
3691
0
       function );
3692
3693
0
      goto on_error;
3694
0
    }
3695
979
    if( libfsext_inode_table_get_inode_by_number(
3696
979
         internal_volume->inode_table,
3697
979
         internal_volume->file_io_handle,
3698
979
         inode_number,
3699
979
         &inode,
3700
979
         error ) != 1 )
3701
242
    {
3702
242
      libcerror_error_set(
3703
242
       error,
3704
242
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3705
242
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3706
242
       "%s: unable to retrieve inode: %" PRIu32 ".",
3707
242
       function,
3708
242
       inode_number );
3709
3710
242
      goto on_error;
3711
242
    }
3712
979
  }
3713
420
  if( result != 0 )
3714
298
  {
3715
298
    if( libfsext_inode_clone(
3716
298
         &safe_inode,
3717
298
         inode,
3718
298
         error ) != 1 )
3719
0
    {
3720
0
      libcerror_error_set(
3721
0
       error,
3722
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3723
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3724
0
       "%s: unable to create inode.",
3725
0
       function );
3726
3727
0
      goto on_error;
3728
0
    }
3729
298
    if( libfsext_directory_entry_clone(
3730
298
         &safe_directory_entry,
3731
298
         directory_entry,
3732
298
         error ) != 1 )
3733
0
    {
3734
0
      libcerror_error_set(
3735
0
       error,
3736
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3737
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3738
0
       "%s: unable to create directory entry.",
3739
0
       function );
3740
3741
0
      goto on_error;
3742
0
    }
3743
298
  }
3744
420
  if( directory != NULL )
3745
420
  {
3746
420
    if( libfsext_directory_free(
3747
420
         &directory,
3748
420
         error ) != 1 )
3749
0
    {
3750
0
      libcerror_error_set(
3751
0
       error,
3752
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3753
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3754
0
       "%s: unable to free directory.",
3755
0
       function );
3756
3757
0
      goto on_error;
3758
0
    }
3759
420
  }
3760
420
  if( result != 0 )
3761
298
  {
3762
    /* libfsext_file_entry_initialize takes over management of safe_inode and safe_directory_entry
3763
     */
3764
298
    if( libfsext_file_entry_initialize(
3765
298
         file_entry,
3766
298
         internal_volume->io_handle,
3767
298
         internal_volume->file_io_handle,
3768
298
         internal_volume->inode_table,
3769
298
         inode_number,
3770
298
         safe_inode,
3771
298
         safe_directory_entry,
3772
298
         error ) != 1 )
3773
54
    {
3774
54
      libcerror_error_set(
3775
54
       error,
3776
54
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3777
54
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3778
54
       "%s: unable to create file entry.",
3779
54
       function );
3780
3781
54
      goto on_error;
3782
54
    }
3783
298
  }
3784
366
  return( result );
3785
3786
1.43k
on_error:
3787
1.43k
  if( safe_directory_entry != NULL )
3788
54
  {
3789
54
    libfsext_directory_entry_free(
3790
54
     &safe_directory_entry,
3791
54
     NULL );
3792
54
  }
3793
1.43k
  if( safe_inode != NULL )
3794
54
  {
3795
54
    libfsext_inode_free(
3796
54
     &safe_inode,
3797
54
     NULL );
3798
54
  }
3799
1.43k
  if( directory != NULL )
3800
663
  {
3801
663
    libfsext_directory_free(
3802
663
     &directory,
3803
663
     NULL );
3804
663
  }
3805
1.43k
  return( -1 );
3806
420
}
3807
3808
/* Retrieves the file entry for an UTF-8 encoded path
3809
 * Returns 1 if successful, 0 if no such file entry or -1 on error
3810
 */
3811
int libfsext_volume_get_file_entry_by_utf8_path(
3812
     libfsext_volume_t *volume,
3813
     const uint8_t *utf8_string,
3814
     size_t utf8_string_length,
3815
     libfsext_file_entry_t **file_entry,
3816
     libcerror_error_t **error )
3817
1.80k
{
3818
1.80k
  libfsext_internal_volume_t *internal_volume = NULL;
3819
1.80k
  static char *function                       = "libfsext_volume_get_file_entry_by_utf8_path";
3820
1.80k
  int result                                  = 0;
3821
3822
1.80k
  if( volume == NULL )
3823
0
  {
3824
0
    libcerror_error_set(
3825
0
     error,
3826
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3827
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3828
0
     "%s: invalid volume.",
3829
0
     function );
3830
3831
0
    return( -1 );
3832
0
  }
3833
1.80k
  internal_volume = (libfsext_internal_volume_t *) volume;
3834
3835
1.80k
  if( file_entry == NULL )
3836
0
  {
3837
0
    libcerror_error_set(
3838
0
     error,
3839
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3840
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3841
0
     "%s: invalid file entry.",
3842
0
     function );
3843
3844
0
    return( -1 );
3845
0
  }
3846
1.80k
  if( *file_entry != NULL )
3847
0
  {
3848
0
    libcerror_error_set(
3849
0
     error,
3850
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3851
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3852
0
     "%s: invalid file entry value already set.",
3853
0
     function );
3854
3855
0
    return( -1 );
3856
0
  }
3857
1.80k
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
3858
1.80k
  if( libcthreads_read_write_lock_grab_for_write(
3859
1.80k
       internal_volume->read_write_lock,
3860
1.80k
       error ) != 1 )
3861
0
  {
3862
0
    libcerror_error_set(
3863
0
     error,
3864
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3865
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3866
0
     "%s: unable to grab read/write lock for writing.",
3867
0
     function );
3868
3869
0
    return( -1 );
3870
0
  }
3871
1.80k
#endif
3872
1.80k
  result = libfsext_internal_volume_get_file_entry_by_utf8_path(
3873
1.80k
            internal_volume,
3874
1.80k
            utf8_string,
3875
1.80k
            utf8_string_length,
3876
1.80k
            file_entry,
3877
1.80k
            error );
3878
3879
1.80k
  if( result == -1 )
3880
1.43k
  {
3881
1.43k
    libcerror_error_set(
3882
1.43k
     error,
3883
1.43k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3884
1.43k
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3885
1.43k
     "%s: unable to retrieve file entry by UTF-8 encoded path.",
3886
1.43k
     function );
3887
3888
1.43k
    result = -1;
3889
1.43k
  }
3890
1.80k
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
3891
1.80k
  if( libcthreads_read_write_lock_release_for_write(
3892
1.80k
       internal_volume->read_write_lock,
3893
1.80k
       error ) != 1 )
3894
0
  {
3895
0
    libcerror_error_set(
3896
0
     error,
3897
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3898
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3899
0
     "%s: unable to release read/write lock for writing.",
3900
0
     function );
3901
3902
0
    libfsext_file_entry_free(
3903
0
     file_entry,
3904
0
     NULL );
3905
3906
0
    return( -1 );
3907
0
  }
3908
1.80k
#endif
3909
1.80k
  return( result );
3910
1.80k
}
3911
3912
/* Retrieves the file entry for an UTF-16 encoded path
3913
 * Returns 1 if successful, 0 if no such file entry or -1 on error
3914
 */
3915
int libfsext_internal_volume_get_file_entry_by_utf16_path(
3916
     libfsext_internal_volume_t *internal_volume,
3917
     const uint16_t *utf16_string,
3918
     size_t utf16_string_length,
3919
     libfsext_file_entry_t **file_entry,
3920
     libcerror_error_t **error )
3921
0
{
3922
0
  libfsext_directory_t *directory                  = NULL;
3923
0
  libfsext_directory_entry_t *directory_entry      = NULL;
3924
0
  libfsext_directory_entry_t *safe_directory_entry = NULL;
3925
0
  libfsext_inode_t *inode                          = NULL;
3926
0
  libfsext_inode_t *safe_inode                     = NULL;
3927
0
  const uint16_t *utf16_string_segment             = NULL;
3928
0
  static char *function                            = "libfsext_internal_volume_get_file_entry_by_utf16_path";
3929
0
  libuna_unicode_character_t unicode_character     = 0;
3930
0
  size_t utf16_string_index                        = 0;
3931
0
  size_t utf16_string_segment_length               = 0;
3932
0
  uint32_t inode_number                            = 0;
3933
0
  int result                                       = 0;
3934
3935
0
  if( internal_volume == NULL )
3936
0
  {
3937
0
    libcerror_error_set(
3938
0
     error,
3939
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3940
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3941
0
     "%s: invalid volume.",
3942
0
     function );
3943
3944
0
    return( -1 );
3945
0
  }
3946
0
  if( utf16_string == NULL )
3947
0
  {
3948
0
    libcerror_error_set(
3949
0
     error,
3950
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3951
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3952
0
     "%s: invalid UTF-16 string.",
3953
0
     function );
3954
3955
0
    return( -1 );
3956
0
  }
3957
0
  if( utf16_string_length > (size_t) SSIZE_MAX )
3958
0
  {
3959
0
    libcerror_error_set(
3960
0
     error,
3961
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3962
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
3963
0
     "%s: invalid UTF-16 string length value exceeds maximum.",
3964
0
     function );
3965
3966
0
    return( -1 );
3967
0
  }
3968
0
  if( file_entry == NULL )
3969
0
  {
3970
0
    libcerror_error_set(
3971
0
     error,
3972
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3973
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3974
0
     "%s: invalid file entry.",
3975
0
     function );
3976
3977
0
    return( -1 );
3978
0
  }
3979
0
  if( *file_entry != NULL )
3980
0
  {
3981
0
    libcerror_error_set(
3982
0
     error,
3983
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3984
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3985
0
     "%s: invalid file entry value already set.",
3986
0
     function );
3987
3988
0
    return( -1 );
3989
0
  }
3990
0
  if( utf16_string_length > 0 )
3991
0
  {
3992
    /* Ignore a leading separator
3993
     */
3994
0
    if( utf16_string[ utf16_string_index ] == (uint16_t) LIBFSEXT_SEPARATOR )
3995
0
    {
3996
0
      utf16_string_index++;
3997
0
    }
3998
0
  }
3999
0
  inode_number = LIBFSEXT_INODE_NUMBER_ROOT_DIRECTORY;
4000
4001
0
  if( libfsext_inode_table_get_inode_by_number(
4002
0
       internal_volume->inode_table,
4003
0
       internal_volume->file_io_handle,
4004
0
       inode_number,
4005
0
       &inode,
4006
0
       error ) != 1 )
4007
0
  {
4008
0
    libcerror_error_set(
4009
0
     error,
4010
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4011
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4012
0
     "%s: unable to retrieve inode: %" PRIu32 ".",
4013
0
     function,
4014
0
     inode_number );
4015
4016
0
    goto on_error;
4017
0
  }
4018
0
  if( ( utf16_string_length == 0 )
4019
0
   || ( utf16_string_length == 1 ) )
4020
0
  {
4021
0
    result = 1;
4022
0
  }
4023
0
  else while( utf16_string_index < utf16_string_length )
4024
0
  {
4025
0
    if( directory != NULL )
4026
0
    {
4027
0
      if( libfsext_directory_free(
4028
0
           &directory,
4029
0
           error ) != 1 )
4030
0
      {
4031
0
        libcerror_error_set(
4032
0
         error,
4033
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4034
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
4035
0
         "%s: unable to free directory.",
4036
0
         function );
4037
4038
0
        goto on_error;
4039
0
      }
4040
0
    }
4041
0
    if( libfsext_directory_initialize(
4042
0
         &directory,
4043
0
         error ) != 1 )
4044
0
    {
4045
0
      libcerror_error_set(
4046
0
       error,
4047
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4048
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4049
0
       "%s: unable to create directory.",
4050
0
       function );
4051
4052
0
      goto on_error;
4053
0
    }
4054
0
    if( libfsext_directory_read_file_io_handle(
4055
0
         directory,
4056
0
         internal_volume->io_handle,
4057
0
         internal_volume->file_io_handle,
4058
0
         inode,
4059
0
         error ) != 1 )
4060
0
    {
4061
0
      libcerror_error_set(
4062
0
       error,
4063
0
       LIBCERROR_ERROR_DOMAIN_IO,
4064
0
       LIBCERROR_IO_ERROR_READ_FAILED,
4065
0
       "%s: unable to read directory from inode: %" PRIu32 ".",
4066
0
       function,
4067
0
       inode_number );
4068
4069
0
      goto on_error;
4070
0
    }
4071
0
    utf16_string_segment        = &( utf16_string[ utf16_string_index ] );
4072
0
    utf16_string_segment_length = utf16_string_index;
4073
4074
0
    while( utf16_string_index < utf16_string_length )
4075
0
    {
4076
0
      if( libuna_unicode_character_copy_from_utf16(
4077
0
           &unicode_character,
4078
0
           utf16_string,
4079
0
           utf16_string_length,
4080
0
           &utf16_string_index,
4081
0
           error ) != 1 )
4082
0
      {
4083
0
        libcerror_error_set(
4084
0
         error,
4085
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4086
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
4087
0
         "%s: unable to copy UTF-16 string to Unicode character.",
4088
0
         function );
4089
4090
0
        goto on_error;
4091
0
      }
4092
0
      if( ( unicode_character == (libuna_unicode_character_t) LIBFSEXT_SEPARATOR )
4093
0
       || ( unicode_character == 0 ) )
4094
0
      {
4095
0
        utf16_string_segment_length += 1;
4096
4097
0
        break;
4098
0
      }
4099
0
    }
4100
0
    utf16_string_segment_length = utf16_string_index - utf16_string_segment_length;
4101
4102
0
    if( utf16_string_segment_length == 0 )
4103
0
    {
4104
0
      result = 0;
4105
0
    }
4106
0
    else
4107
0
    {
4108
0
      result = libfsext_directory_get_entry_by_utf16_name(
4109
0
                directory,
4110
0
                utf16_string_segment,
4111
0
                utf16_string_segment_length,
4112
0
                &directory_entry,
4113
0
                error );
4114
0
    }
4115
0
    if( result == -1 )
4116
0
    {
4117
0
      libcerror_error_set(
4118
0
       error,
4119
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4120
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4121
0
       "%s: unable to retrieve directory entry by UTF-16 name.",
4122
0
       function );
4123
4124
0
      goto on_error;
4125
0
    }
4126
0
    else if( result == 0 )
4127
0
    {
4128
0
      break;
4129
0
    }
4130
0
    if( libfsext_directory_entry_get_inode_number(
4131
0
         directory_entry,
4132
0
         &inode_number,
4133
0
         error ) != 1 )
4134
0
    {
4135
0
      libcerror_error_set(
4136
0
       error,
4137
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4138
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4139
0
       "%s: unable to retrieve inode number from directory entry.",
4140
0
       function );
4141
4142
0
      goto on_error;
4143
0
    }
4144
0
    if( libfsext_inode_table_get_inode_by_number(
4145
0
         internal_volume->inode_table,
4146
0
         internal_volume->file_io_handle,
4147
0
         inode_number,
4148
0
         &inode,
4149
0
         error ) != 1 )
4150
0
    {
4151
0
      libcerror_error_set(
4152
0
       error,
4153
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4154
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4155
0
       "%s: unable to retrieve inode: %" PRIu32 ".",
4156
0
       function,
4157
0
       inode_number );
4158
4159
0
      goto on_error;
4160
0
    }
4161
0
  }
4162
0
  if( result != 0 )
4163
0
  {
4164
0
    if( libfsext_inode_clone(
4165
0
         &safe_inode,
4166
0
         inode,
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_INITIALIZE_FAILED,
4173
0
       "%s: unable to create inode.",
4174
0
       function );
4175
4176
0
      goto on_error;
4177
0
    }
4178
0
    if( libfsext_directory_entry_clone(
4179
0
         &safe_directory_entry,
4180
0
         directory_entry,
4181
0
         error ) != 1 )
4182
0
    {
4183
0
      libcerror_error_set(
4184
0
       error,
4185
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4186
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4187
0
       "%s: unable to create directory entry.",
4188
0
       function );
4189
4190
0
      goto on_error;
4191
0
    }
4192
0
  }
4193
0
  if( directory != NULL )
4194
0
  {
4195
0
    if( libfsext_directory_free(
4196
0
         &directory,
4197
0
         error ) != 1 )
4198
0
    {
4199
0
      libcerror_error_set(
4200
0
       error,
4201
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4202
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
4203
0
       "%s: unable to free directory.",
4204
0
       function );
4205
4206
0
      goto on_error;
4207
0
    }
4208
0
  }
4209
0
  if( result != 0 )
4210
0
  {
4211
    /* libfsext_file_entry_initialize takes over management of safe_inode and safe_directory_entry
4212
     */
4213
0
    if( libfsext_file_entry_initialize(
4214
0
         file_entry,
4215
0
         internal_volume->io_handle,
4216
0
         internal_volume->file_io_handle,
4217
0
         internal_volume->inode_table,
4218
0
         inode_number,
4219
0
         safe_inode,
4220
0
         safe_directory_entry,
4221
0
         error ) != 1 )
4222
0
    {
4223
0
      libcerror_error_set(
4224
0
       error,
4225
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4226
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4227
0
       "%s: unable to create file entry.",
4228
0
       function );
4229
4230
0
      goto on_error;
4231
0
    }
4232
0
  }
4233
0
  return( result );
4234
4235
0
on_error:
4236
0
  if( safe_directory_entry != NULL )
4237
0
  {
4238
0
    libfsext_directory_entry_free(
4239
0
     &safe_directory_entry,
4240
0
     NULL );
4241
0
  }
4242
0
  if( safe_inode != NULL )
4243
0
  {
4244
0
    libfsext_inode_free(
4245
0
     &safe_inode,
4246
0
     NULL );
4247
0
  }
4248
0
  if( directory != NULL )
4249
0
  {
4250
0
    libfsext_directory_free(
4251
0
     &directory,
4252
0
     NULL );
4253
0
  }
4254
0
  return( -1 );
4255
0
}
4256
4257
/* Retrieves the file entry for an UTF-16 encoded path
4258
 * Returns 1 if successful, 0 if no such file entry or -1 on error
4259
 */
4260
int libfsext_volume_get_file_entry_by_utf16_path(
4261
     libfsext_volume_t *volume,
4262
     const uint16_t *utf16_string,
4263
     size_t utf16_string_length,
4264
     libfsext_file_entry_t **file_entry,
4265
     libcerror_error_t **error )
4266
0
{
4267
0
  libfsext_internal_volume_t *internal_volume = NULL;
4268
0
  static char *function                       = "libfsext_volume_get_file_entry_by_utf16_path";
4269
0
  int result                                  = 0;
4270
4271
0
  if( volume == NULL )
4272
0
  {
4273
0
    libcerror_error_set(
4274
0
     error,
4275
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4276
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4277
0
     "%s: invalid volume.",
4278
0
     function );
4279
4280
0
    return( -1 );
4281
0
  }
4282
0
  internal_volume = (libfsext_internal_volume_t *) volume;
4283
4284
0
  if( file_entry == NULL )
4285
0
  {
4286
0
    libcerror_error_set(
4287
0
     error,
4288
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4289
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4290
0
     "%s: invalid file entry.",
4291
0
     function );
4292
4293
0
    return( -1 );
4294
0
  }
4295
0
  if( *file_entry != NULL )
4296
0
  {
4297
0
    libcerror_error_set(
4298
0
     error,
4299
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4300
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4301
0
     "%s: invalid file entry value already set.",
4302
0
     function );
4303
4304
0
    return( -1 );
4305
0
  }
4306
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
4307
0
  if( libcthreads_read_write_lock_grab_for_write(
4308
0
       internal_volume->read_write_lock,
4309
0
       error ) != 1 )
4310
0
  {
4311
0
    libcerror_error_set(
4312
0
     error,
4313
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4314
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4315
0
     "%s: unable to grab read/write lock for writing.",
4316
0
     function );
4317
4318
0
    return( -1 );
4319
0
  }
4320
0
#endif
4321
0
  result = libfsext_internal_volume_get_file_entry_by_utf16_path(
4322
0
            internal_volume,
4323
0
            utf16_string,
4324
0
            utf16_string_length,
4325
0
            file_entry,
4326
0
            error );
4327
4328
0
  if( result == -1 )
4329
0
  {
4330
0
    libcerror_error_set(
4331
0
     error,
4332
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4333
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4334
0
     "%s: unable to retrieve file entry by UTF-16 encoded path.",
4335
0
     function );
4336
4337
0
    result = -1;
4338
0
  }
4339
0
#if defined( HAVE_LIBFSEXT_MULTI_THREAD_SUPPORT )
4340
0
  if( libcthreads_read_write_lock_release_for_write(
4341
0
       internal_volume->read_write_lock,
4342
0
       error ) != 1 )
4343
0
  {
4344
0
    libcerror_error_set(
4345
0
     error,
4346
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4347
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4348
0
     "%s: unable to release read/write lock for writing.",
4349
0
     function );
4350
4351
0
    libfsext_file_entry_free(
4352
0
     file_entry,
4353
0
     NULL );
4354
4355
0
    return( -1 );
4356
0
  }
4357
0
#endif
4358
0
  return( result );
4359
0
}
4360