Coverage Report

Created: 2023-06-07 06:53

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