Coverage Report

Created: 2025-06-13 07:22

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