Coverage Report

Created: 2026-05-24 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvslvm/libvslvm/libvslvm_logical_volume.c
Line
Count
Source
1
/*
2
 * Logical volume functions
3
 *
4
 * Copyright (C) 2014-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <narrow_string.h>
25
#include <types.h>
26
27
#include "libvslvm_chunk_data.h"
28
#include "libvslvm_data_area_descriptor.h"
29
#include "libvslvm_definitions.h"
30
#include "libvslvm_io_handle.h"
31
#include "libvslvm_libbfio.h"
32
#include "libvslvm_libcerror.h"
33
#include "libvslvm_libcthreads.h"
34
#include "libvslvm_libfcache.h"
35
#include "libvslvm_libfdata.h"
36
#include "libvslvm_logical_volume.h"
37
#include "libvslvm_logical_volume_values.h"
38
#include "libvslvm_physical_volume.h"
39
#include "libvslvm_segment.h"
40
#include "libvslvm_stripe.h"
41
#include "libvslvm_types.h"
42
#include "libvslvm_unused.h"
43
#include "libvslvm_volume_group.h"
44
45
/* Creates a logical volume
46
 * Make sure the value logical_volume is referencing, is set to NULL
47
 * Returns 1 if successful or -1 on error
48
 */
49
int libvslvm_logical_volume_initialize(
50
     libvslvm_logical_volume_t **logical_volume,
51
     libvslvm_io_handle_t *io_handle,
52
     libvslvm_volume_group_t *volume_group,
53
     libbfio_pool_t *physical_volume_file_io_pool,
54
     libvslvm_logical_volume_values_t *logical_volume_values,
55
     libcerror_error_t **error )
56
284
{
57
284
  char physical_volume_name[ 64 ];
58
59
284
  libvslvm_data_area_descriptor_t *data_area_descriptor       = NULL;
60
284
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
61
284
  libvslvm_physical_volume_t *physical_volume                 = NULL;
62
284
  libvslvm_segment_t *segment                                 = NULL;
63
284
  libvslvm_stripe_t *stripe                                   = NULL;
64
284
  static char *function                                       = "libvslvm_logical_volume_initialize";
65
284
  off64_t segment_offset                                      = 0;
66
284
  off64_t stripe_offset                                       = 0;
67
284
  size64_t segment_size                                       = 0;
68
284
  size_t physical_volume_name_length                          = 0;
69
284
  int element_index                                           = 0;
70
284
  int number_of_segments                                      = 0;
71
284
  int number_of_stripes                                       = 0;
72
284
  int result                                                  = 0;
73
284
  int segment_index                                           = 0;
74
284
  int stripe_index                                            = 0;
75
76
284
  if( logical_volume == NULL )
77
0
  {
78
0
    libcerror_error_set(
79
0
     error,
80
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
81
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
82
0
     "%s: invalid logical volume.",
83
0
     function );
84
85
0
    return( -1 );
86
0
  }
87
284
  if( *logical_volume != NULL )
88
0
  {
89
0
    libcerror_error_set(
90
0
     error,
91
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
92
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
93
0
     "%s: invalid logical volume value already set.",
94
0
     function );
95
96
0
    return( -1 );
97
0
  }
98
284
  if( logical_volume_values == NULL )
99
0
  {
100
0
    libcerror_error_set(
101
0
     error,
102
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
103
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
104
0
     "%s: invalid logical volume values.",
105
0
     function );
106
107
0
    return( -1 );
108
0
  }
109
284
  internal_logical_volume = memory_allocate_structure(
110
284
                             libvslvm_internal_logical_volume_t );
111
112
284
  if( internal_logical_volume == NULL )
113
0
  {
114
0
    libcerror_error_set(
115
0
     error,
116
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
117
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
118
0
     "%s: unable to create logical volume.",
119
0
     function );
120
121
0
    goto on_error;
122
0
  }
123
284
  if( memory_set(
124
284
       internal_logical_volume,
125
284
       0,
126
284
       sizeof( libvslvm_internal_logical_volume_t ) ) == NULL )
127
0
  {
128
0
    libcerror_error_set(
129
0
     error,
130
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
131
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
132
0
     "%s: unable to clear logical volume.",
133
0
     function );
134
135
0
    memory_free(
136
0
     internal_logical_volume );
137
138
0
    return( -1 );
139
0
  }
140
/* TODO determine how the LVM raid chunk size is determined, 64k seems to be pretty standard */
141
284
  if( libfdata_vector_initialize(
142
284
       &( internal_logical_volume->chunks_vector ),
143
284
       (size64_t) ( 64 * 1024 ),
144
284
       NULL,
145
284
       NULL,
146
284
       NULL,
147
284
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libvslvm_logical_volume_read_chunk_data,
148
284
       NULL,
149
284
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
150
284
       error ) != 1 )
151
0
  {
152
0
    libcerror_error_set(
153
0
     error,
154
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
155
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
156
0
     "%s: unable to create chunks vector.",
157
0
     function );
158
159
0
    goto on_error;
160
0
  }
161
284
  if( libvslvm_logical_volume_values_get_number_of_segments(
162
284
       logical_volume_values,
163
284
       &number_of_segments,
164
284
       error ) != 1 )
165
0
  {
166
0
    libcerror_error_set(
167
0
     error,
168
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
169
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
170
0
     "%s: unable to retrieve number of segments.",
171
0
     function );
172
173
0
    goto on_error;
174
0
  }
175
284
  for( segment_index = 0;
176
319
       segment_index < number_of_segments;
177
284
       segment_index++ )
178
282
  {
179
282
    if( libvslvm_logical_volume_values_get_segment(
180
282
         logical_volume_values,
181
282
         segment_index,
182
282
         &segment,
183
282
         error ) != 1 )
184
0
    {
185
0
      libcerror_error_set(
186
0
       error,
187
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
188
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
189
0
       "%s: unable to retrieve segment: %d.",
190
0
       function,
191
0
       segment_index );
192
193
0
      goto on_error;
194
0
    }
195
282
    if( libvslvm_segment_get_range(
196
282
         segment,
197
282
         &segment_offset,
198
282
         &segment_size,
199
282
         error ) != 1 )
200
0
    {
201
0
      libcerror_error_set(
202
0
       error,
203
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
204
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
205
0
       "%s: unable to retrieve segment: %d range.",
206
0
       function,
207
0
       segment_index );
208
209
0
      goto on_error;
210
0
    }
211
282
    if( libvslvm_segment_get_number_of_stripes(
212
282
         segment,
213
282
         &number_of_stripes,
214
282
         error ) != 1 )
215
0
    {
216
0
      libcerror_error_set(
217
0
       error,
218
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
219
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
220
0
       "%s: unable to retrieve number of stripes.",
221
0
       function );
222
223
0
      goto on_error;
224
0
    }
225
/* TODO add support for multi stripe segments */
226
282
    if( number_of_stripes != 1 )
227
27
    {
228
27
      libcerror_error_set(
229
27
       error,
230
27
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
231
27
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
232
27
       "%s: unsupported number of stripes.",
233
27
       function );
234
235
27
      goto on_error;
236
27
    }
237
255
    for( stripe_index = 0;
238
413
         stripe_index < number_of_stripes;
239
255
         stripe_index++ )
240
255
    {
241
255
      if( libvslvm_segment_get_stripe(
242
255
           segment,
243
255
           stripe_index,
244
255
           &stripe,
245
255
           error ) != 1 )
246
0
      {
247
0
        libcerror_error_set(
248
0
         error,
249
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
250
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
251
0
         "%s: unable to retrieve stripe: %d.",
252
0
         function,
253
0
         stripe_index );
254
255
0
        goto on_error;
256
0
      }
257
255
      if( libvslvm_stripe_get_physical_volume_name(
258
255
           stripe,
259
255
           physical_volume_name,
260
255
           64,
261
255
           error ) != 1 )
262
13
      {
263
13
        libcerror_error_set(
264
13
         error,
265
13
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
266
13
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
267
13
         "%s: unable to retrieve stripe: %d physical volume name.",
268
13
         function,
269
13
         stripe_index );
270
271
13
        goto on_error;
272
13
      }
273
242
      if( libvslvm_stripe_get_data_area_offset(
274
242
           stripe,
275
242
           &stripe_offset,
276
242
           error ) != 1 )
277
0
      {
278
0
        libcerror_error_set(
279
0
         error,
280
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
281
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
282
0
         "%s: unable to retrieve stripe: %d data area offset.",
283
0
         function,
284
0
         stripe_index );
285
286
0
        goto on_error;
287
0
      }
288
242
      if( libvslvm_stripe_free(
289
242
           &stripe,
290
242
           error ) != 1 )
291
0
      {
292
0
        libcerror_error_set(
293
0
         error,
294
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
295
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
296
0
         "%s: unable to free stripe: %d.",
297
0
         function,
298
0
         stripe_index );
299
300
0
        goto on_error;
301
0
      }
302
242
      physical_volume_name_length = narrow_string_length(
303
242
                                     physical_volume_name );
304
305
242
      if( libvslvm_volume_group_get_physical_volume_by_name(
306
242
           volume_group,
307
242
           physical_volume_name,
308
242
           physical_volume_name_length,
309
242
           &physical_volume,
310
242
           error ) != 1 )
311
84
      {
312
84
        libcerror_error_set(
313
84
         error,
314
84
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
315
84
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
316
84
         "%s: unable to retrieve physical volume by name.",
317
84
         function );
318
319
84
        goto on_error;
320
84
      }
321
158
      result = libvslvm_physical_volume_get_data_area_descriptor_by_offset(
322
158
                physical_volume,
323
158
                stripe_offset,
324
158
                &data_area_descriptor,
325
158
                error );
326
327
158
      if( result == -1 )
328
0
      {
329
0
        libcerror_error_set(
330
0
         error,
331
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
332
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
333
0
         "%s: unable to retrieve data area descriptor by offset: 0x%08" PRIx64 ".",
334
0
         function,
335
0
         segment_offset );
336
337
0
        goto on_error;
338
0
      }
339
158
      else if( result != 0 )
340
51
      {
341
51
        if( data_area_descriptor == NULL )
342
0
        {
343
0
          libcerror_error_set(
344
0
           error,
345
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
346
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
347
0
           "%s: missing data area descriptor.",
348
0
           function );
349
350
0
          goto on_error;
351
0
        }
352
        /* The stripe data area offset is relative to the start
353
         * of the data area of the volume
354
         */
355
51
        stripe_offset += data_area_descriptor->offset;
356
51
      }
357
/* TODO check segment size ? */
358
158
    }
359
/* TODO skip the append if the physical volumes are not available? */
360
158
    if( libfdata_vector_append_segment(
361
158
         internal_logical_volume->chunks_vector,
362
158
         &element_index,
363
158
         0,
364
158
         stripe_offset,
365
158
         segment_size,
366
158
         0,
367
158
         error ) != 1 )
368
123
    {
369
123
      libcerror_error_set(
370
123
       error,
371
123
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
372
123
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
373
123
       "%s: unable to append segment to chunks vector.",
374
123
       function );
375
376
123
      goto on_error;
377
123
    }
378
35
    segment = NULL;
379
35
  }
380
37
  if( libfdata_vector_get_size(
381
37
       internal_logical_volume->chunks_vector,
382
37
       &( internal_logical_volume->size ),
383
37
       error ) != 1 )
384
0
  {
385
0
    libcerror_error_set(
386
0
     error,
387
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
388
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
389
0
     "%s: unable to retrieve size from chunks vector.",
390
0
     function );
391
392
0
    goto on_error;
393
0
  }
394
37
  if( libfcache_cache_initialize(
395
37
       &( internal_logical_volume->chunks_cache ),
396
37
       LIBVSLVM_MAXIMUM_CACHE_ENTRIES_CHUNKS,
397
37
       error ) != 1 )
398
0
  {
399
0
    libcerror_error_set(
400
0
     error,
401
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
402
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
403
0
     "%s: unable to create chunks cache.",
404
0
     function );
405
406
0
    goto on_error;
407
0
  }
408
37
#if defined( HAVE_MULTI_THREAD_SUPPORT )
409
37
  if( libcthreads_read_write_lock_initialize(
410
37
       &( internal_logical_volume->read_write_lock ),
411
37
       error ) != 1 )
412
0
  {
413
0
    libcerror_error_set(
414
0
     error,
415
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
416
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
417
0
     "%s: unable to initialize read/write lock.",
418
0
     function );
419
420
0
    goto on_error;
421
0
  }
422
37
#endif
423
37
  internal_logical_volume->io_handle                    = io_handle;
424
37
  internal_logical_volume->physical_volume_file_io_pool = physical_volume_file_io_pool;
425
37
  internal_logical_volume->logical_volume_values        = logical_volume_values;
426
427
37
  *logical_volume= (libvslvm_logical_volume_t *) internal_logical_volume;
428
429
37
  return( 1 );
430
431
247
on_error:
432
247
  if( stripe != NULL )
433
13
  {
434
13
    libvslvm_stripe_free(
435
13
     &stripe,
436
13
     NULL );
437
13
  }
438
247
  if( internal_logical_volume != NULL )
439
247
  {
440
247
    if( internal_logical_volume->chunks_cache != NULL )
441
0
    {
442
0
      libfcache_cache_free(
443
0
       &( internal_logical_volume->chunks_cache ),
444
0
       NULL );
445
0
    }
446
247
    if( internal_logical_volume->chunks_vector != NULL )
447
247
    {
448
247
      libfdata_vector_free(
449
247
       &( internal_logical_volume->chunks_vector ),
450
247
       NULL );
451
247
    }
452
247
    memory_free(
453
247
     internal_logical_volume );
454
247
  }
455
247
  return( -1 );
456
37
}
457
458
/* Frees a logical volume
459
 * Returns 1 if successful or -1 on error
460
 */
461
int libvslvm_logical_volume_free(
462
     libvslvm_logical_volume_t **logical_volume,
463
     libcerror_error_t **error )
464
37
{
465
37
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
466
37
  static char *function                                       = "libvslvm_logical_volume_free";
467
37
  int result                                                  = 1;
468
469
37
  if( logical_volume == NULL )
470
0
  {
471
0
    libcerror_error_set(
472
0
     error,
473
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
474
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
475
0
     "%s: invalid logical volume.",
476
0
     function );
477
478
0
    return( -1 );
479
0
  }
480
37
  if( *logical_volume != NULL )
481
37
  {
482
37
    internal_logical_volume = (libvslvm_internal_logical_volume_t *) *logical_volume;
483
37
    *logical_volume         = NULL;
484
485
    /* The logical_volume_values and physical_volume_file_io_pool references are freed elsewhere
486
     */
487
37
    if( libfdata_vector_free(
488
37
         &( internal_logical_volume->chunks_vector ),
489
37
         error ) != 1 )
490
0
    {
491
0
      libcerror_error_set(
492
0
       error,
493
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
494
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
495
0
       "%s: unable to free chunks vector.",
496
0
       function );
497
498
0
      result = -1;
499
0
    }
500
37
    if( libfcache_cache_free(
501
37
         &( internal_logical_volume->chunks_cache ),
502
37
         error ) != 1 )
503
0
    {
504
0
      libcerror_error_set(
505
0
       error,
506
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
507
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
508
0
       "%s: unable to free chunks cache.",
509
0
       function );
510
511
0
      result = -1;
512
0
    }
513
37
#if defined( HAVE_MULTI_THREAD_SUPPORT )
514
37
    if( libcthreads_read_write_lock_free(
515
37
         &( internal_logical_volume->read_write_lock ),
516
37
         error ) != 1 )
517
0
    {
518
0
      libcerror_error_set(
519
0
       error,
520
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
521
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
522
0
       "%s: unable to free read/write lock.",
523
0
       function );
524
525
0
      result = -1;
526
0
    }
527
37
#endif
528
37
    memory_free(
529
37
     internal_logical_volume );
530
37
  }
531
37
  return( result );
532
37
}
533
534
/* Reads (logical volume) data at the current offset into a buffer using a Basic File IO (bfio) pool
535
 * This function is not multi-thread safe acquire write lock before call
536
 * Returns the number of bytes read or -1 on error
537
 */
538
ssize_t libvslvm_internal_logical_volume_read_buffer_from_file_io_pool(
539
         libvslvm_internal_logical_volume_t *internal_logical_volume,
540
         libbfio_pool_t *physical_volume_file_io_pool,
541
         void *buffer,
542
         size_t buffer_size,
543
         libcerror_error_t **error )
544
0
{
545
0
  libvslvm_chunk_data_t *chunk_data = NULL;
546
0
  static char *function             = "libvslvm_internal_logical_volume_read_buffer_from_file_io_pool";
547
0
  off64_t element_data_offset       = 0;
548
0
  size_t buffer_offset              = 0;
549
0
  size_t read_size                  = 0;
550
551
0
  if( internal_logical_volume == NULL )
552
0
  {
553
0
    libcerror_error_set(
554
0
     error,
555
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
556
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
557
0
     "%s: invalid logical volume.",
558
0
     function );
559
560
0
    return( -1 );
561
0
  }
562
0
  if( internal_logical_volume->current_offset < 0 )
563
0
  {
564
0
    libcerror_error_set(
565
0
     error,
566
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
567
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
568
0
     "%s: invalid logical volume - current offset value out of bounds.",
569
0
     function );
570
571
0
    return( -1 );
572
0
  }
573
0
  if( buffer_size == 0 )
574
0
  {
575
0
    return( 0 );
576
0
  }
577
0
  if( (size64_t) internal_logical_volume->current_offset >= internal_logical_volume->size )
578
0
  {
579
0
    return( 0 );
580
0
  }
581
0
  if( (size64_t) ( internal_logical_volume->current_offset + buffer_size ) > internal_logical_volume->size )
582
0
  {
583
0
    buffer_size = (size_t) ( internal_logical_volume->size - internal_logical_volume->current_offset );
584
0
  }
585
0
  while( buffer_size > 0 )
586
0
  {
587
0
    if( libfdata_vector_get_element_value_at_offset(
588
0
         internal_logical_volume->chunks_vector,
589
0
         (intptr_t *) physical_volume_file_io_pool,
590
0
         (libfdata_cache_t *) internal_logical_volume->chunks_cache,
591
0
         internal_logical_volume->current_offset,
592
0
         &element_data_offset,
593
0
         (intptr_t **) &chunk_data,
594
0
         0,
595
0
         error ) != 1 )
596
0
    {
597
0
      libcerror_error_set(
598
0
       error,
599
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
600
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
601
0
       "%s: unable to retrieve chunk data at offset: 0x%08" PRIx64 ".",
602
0
       function,
603
0
       internal_logical_volume->current_offset );
604
605
0
      return( -1 );
606
0
    }
607
0
    if( chunk_data == NULL )
608
0
    {
609
0
      libcerror_error_set(
610
0
       error,
611
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
612
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
613
0
       "%s: missing chunk data.",
614
0
       function );
615
616
0
      return( -1 );
617
0
    }
618
0
    read_size = chunk_data->data_size - (size_t) element_data_offset;
619
620
0
    if( buffer_size < read_size )
621
0
    {
622
0
      read_size = buffer_size;
623
0
    }
624
0
    if( memory_copy(
625
0
         &( ( (uint8_t *) buffer )[ buffer_offset ] ),
626
0
         &( chunk_data->data[ element_data_offset ] ),
627
0
         read_size ) == NULL )
628
0
    {
629
0
      libcerror_error_set(
630
0
       error,
631
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
632
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
633
0
       "%s: unable to copy chunk data.",
634
0
       function );
635
636
0
      return( -1 );
637
0
    }
638
0
    internal_logical_volume->current_offset += read_size;
639
0
    buffer_offset                           += read_size;
640
0
    buffer_size                             -= read_size;
641
0
  }
642
0
  return( (ssize_t) buffer_offset );
643
0
}
644
645
/* Reads (logical volume) data at the current offset into a buffer
646
 * Returns the number of bytes read or -1 on error
647
 */
648
ssize_t libvslvm_logical_volume_read_buffer(
649
         libvslvm_logical_volume_t *logical_volume,
650
         void *buffer,
651
         size_t buffer_size,
652
         libcerror_error_t **error )
653
0
{
654
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
655
0
  static char *function                                       = "libvslvm_logical_volume_read_buffer";
656
0
  ssize_t read_count                                          = 0;
657
658
0
  if( logical_volume == NULL )
659
0
  {
660
0
    libcerror_error_set(
661
0
     error,
662
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
663
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
664
0
     "%s: invalid logical volume.",
665
0
     function );
666
667
0
    return( -1 );
668
0
  }
669
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
670
671
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
672
0
  if( libcthreads_read_write_lock_grab_for_write(
673
0
       internal_logical_volume->read_write_lock,
674
0
       error ) != 1 )
675
0
  {
676
0
    libcerror_error_set(
677
0
     error,
678
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
679
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
680
0
     "%s: unable to grab read/write lock for writing.",
681
0
     function );
682
683
0
    return( -1 );
684
0
  }
685
0
#endif
686
0
  read_count = libvslvm_internal_logical_volume_read_buffer_from_file_io_pool(
687
0
          internal_logical_volume,
688
0
          internal_logical_volume->physical_volume_file_io_pool,
689
0
          buffer,
690
0
          buffer_size,
691
0
          error );
692
693
0
  if( read_count == -1 )
694
0
  {
695
0
    libcerror_error_set(
696
0
     error,
697
0
     LIBCERROR_ERROR_DOMAIN_IO,
698
0
     LIBCERROR_IO_ERROR_READ_FAILED,
699
0
     "%s: unable to read buffer from logical volume.",
700
0
     function );
701
702
0
    read_count = -1;
703
0
  }
704
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
705
0
  if( libcthreads_read_write_lock_release_for_write(
706
0
       internal_logical_volume->read_write_lock,
707
0
       error ) != 1 )
708
0
  {
709
0
    libcerror_error_set(
710
0
     error,
711
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
712
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
713
0
     "%s: unable to release read/write lock for writing.",
714
0
     function );
715
716
0
    return( -1 );
717
0
  }
718
0
#endif
719
0
  return( read_count );
720
0
}
721
722
/* Reads (logical volume) data at a specific offset
723
 * Returns the number of bytes read or -1 on error
724
 */
725
ssize_t libvslvm_logical_volume_read_buffer_at_offset(
726
         libvslvm_logical_volume_t *logical_volume,
727
         void *buffer,
728
         size_t buffer_size,
729
         off64_t offset,
730
         libcerror_error_t **error )
731
0
{
732
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
733
0
  static char *function                                       = "libvslvm_logical_volume_read_buffer_at_offset";
734
0
  ssize_t read_count                                          = 0;
735
736
0
  if( logical_volume == NULL )
737
0
  {
738
0
    libcerror_error_set(
739
0
     error,
740
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
741
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
742
0
     "%s: invalid logical volume.",
743
0
     function );
744
745
0
    return( -1 );
746
0
  }
747
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
748
749
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
750
0
  if( libcthreads_read_write_lock_grab_for_write(
751
0
       internal_logical_volume->read_write_lock,
752
0
       error ) != 1 )
753
0
  {
754
0
    libcerror_error_set(
755
0
     error,
756
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
757
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
758
0
     "%s: unable to grab read/write lock for writing.",
759
0
     function );
760
761
0
    return( -1 );
762
0
  }
763
0
#endif
764
0
  if( libvslvm_internal_logical_volume_seek_offset(
765
0
       internal_logical_volume,
766
0
       offset,
767
0
       SEEK_SET,
768
0
       error ) == -1 )
769
0
  {
770
0
    libcerror_error_set(
771
0
     error,
772
0
     LIBCERROR_ERROR_DOMAIN_IO,
773
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
774
0
     "%s: unable to seek offset.",
775
0
     function );
776
777
0
    goto on_error;
778
0
  }
779
0
  read_count = libvslvm_internal_logical_volume_read_buffer_from_file_io_pool(
780
0
          internal_logical_volume,
781
0
          internal_logical_volume->physical_volume_file_io_pool,
782
0
          buffer,
783
0
          buffer_size,
784
0
          error );
785
786
0
  if( read_count == -1 )
787
0
  {
788
0
    libcerror_error_set(
789
0
     error,
790
0
     LIBCERROR_ERROR_DOMAIN_IO,
791
0
     LIBCERROR_IO_ERROR_READ_FAILED,
792
0
     "%s: unable to read buffer.",
793
0
     function );
794
795
0
    goto on_error;
796
0
  }
797
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
798
0
  if( libcthreads_read_write_lock_release_for_write(
799
0
       internal_logical_volume->read_write_lock,
800
0
       error ) != 1 )
801
0
  {
802
0
    libcerror_error_set(
803
0
     error,
804
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
805
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
806
0
     "%s: unable to release read/write lock for writing.",
807
0
     function );
808
809
0
    return( -1 );
810
0
  }
811
0
#endif
812
0
  return( read_count );
813
814
0
on_error:
815
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
816
0
  libcthreads_read_write_lock_release_for_write(
817
0
   internal_logical_volume->read_write_lock,
818
0
   NULL );
819
0
#endif
820
0
  return( -1 );
821
0
}
822
823
/* Seeks a certain offset of the (logical volume) data
824
 * This function is not multi-thread safe acquire write lock before call
825
 * Returns the offset if seek is successful or -1 on error
826
 */
827
off64_t libvslvm_internal_logical_volume_seek_offset(
828
         libvslvm_internal_logical_volume_t *internal_logical_volume,
829
         off64_t offset,
830
         int whence,
831
         libcerror_error_t **error )
832
0
{
833
0
  static char *function = "libvslvm_internal_logical_volume_seek_offset";
834
835
0
  if( internal_logical_volume == NULL )
836
0
  {
837
0
    libcerror_error_set(
838
0
     error,
839
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
840
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
841
0
     "%s: invalid logical volume.",
842
0
     function );
843
844
0
    return( -1 );
845
0
  }
846
0
  if( ( whence != SEEK_CUR )
847
0
   && ( whence != SEEK_END )
848
0
   && ( whence != SEEK_SET ) )
849
0
  {
850
0
    libcerror_error_set(
851
0
     error,
852
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
853
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
854
0
     "%s: unsupported whence.",
855
0
     function );
856
857
0
    return( -1 );
858
0
  }
859
0
  if( whence == SEEK_CUR )
860
0
  {
861
0
    offset += internal_logical_volume->current_offset;
862
0
  }
863
0
  else if( whence == SEEK_END )
864
0
  {
865
0
    offset += (off64_t) internal_logical_volume->size;
866
0
  }
867
0
  if( offset < 0 )
868
0
  {
869
0
    libcerror_error_set(
870
0
     error,
871
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
872
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
873
0
     "%s: invalid offset value out of bounds.",
874
0
     function );
875
876
0
    return( -1 );
877
0
  }
878
0
  internal_logical_volume->current_offset = offset;
879
880
0
  return( offset );
881
0
}
882
883
/* Seeks a certain offset of the (logical volume) data
884
 * Returns the offset if seek is successful or -1 on error
885
 */
886
off64_t libvslvm_logical_volume_seek_offset(
887
         libvslvm_logical_volume_t *logical_volume,
888
         off64_t offset,
889
         int whence,
890
         libcerror_error_t **error )
891
0
{
892
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
893
0
  static char *function                                       = "libvslvm_logical_volume_seek_offset";
894
895
0
  if( logical_volume == NULL )
896
0
  {
897
0
    libcerror_error_set(
898
0
     error,
899
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
900
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
901
0
     "%s: invalid logical volume.",
902
0
     function );
903
904
0
    return( -1 );
905
0
  }
906
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
907
908
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
909
0
  if( libcthreads_read_write_lock_grab_for_write(
910
0
       internal_logical_volume->read_write_lock,
911
0
       error ) != 1 )
912
0
  {
913
0
    libcerror_error_set(
914
0
     error,
915
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
916
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
917
0
     "%s: unable to grab read/write lock for writing.",
918
0
     function );
919
920
0
    return( -1 );
921
0
  }
922
0
#endif
923
0
  offset = libvslvm_internal_logical_volume_seek_offset(
924
0
            internal_logical_volume,
925
0
            offset,
926
0
            whence,
927
0
            error );
928
929
0
  if( offset == -1 )
930
0
  {
931
0
    libcerror_error_set(
932
0
     error,
933
0
     LIBCERROR_ERROR_DOMAIN_IO,
934
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
935
0
     "%s: unable to seek offset.",
936
0
     function );
937
938
0
    offset = -1;
939
0
  }
940
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
941
0
  if( libcthreads_read_write_lock_release_for_write(
942
0
       internal_logical_volume->read_write_lock,
943
0
       error ) != 1 )
944
0
  {
945
0
    libcerror_error_set(
946
0
     error,
947
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
948
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
949
0
     "%s: unable to release read/write lock for writing.",
950
0
     function );
951
952
0
    return( -1 );
953
0
  }
954
0
#endif
955
0
  return( offset );
956
0
}
957
958
/* Retrieves the current offset of the (logical volume) data
959
 * Returns 1 if successful or -1 on error
960
 */
961
int libvslvm_logical_volume_get_offset(
962
     libvslvm_logical_volume_t *logical_volume,
963
     off64_t *offset,
964
     libcerror_error_t **error )
965
0
{
966
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
967
0
  static char *function                                       = "libvslvm_logical_volume_get_offset";
968
969
0
  if( logical_volume == NULL )
970
0
  {
971
0
    libcerror_error_set(
972
0
     error,
973
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
974
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
975
0
     "%s: invalid logical volume.",
976
0
     function );
977
978
0
    return( -1 );
979
0
  }
980
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
981
982
0
  if( offset == NULL )
983
0
  {
984
0
    libcerror_error_set(
985
0
     error,
986
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
987
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
988
0
     "%s: invalid offset.",
989
0
     function );
990
991
0
    return( -1 );
992
0
  }
993
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
994
0
  if( libcthreads_read_write_lock_grab_for_read(
995
0
       internal_logical_volume->read_write_lock,
996
0
       error ) != 1 )
997
0
  {
998
0
    libcerror_error_set(
999
0
     error,
1000
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1001
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1002
0
     "%s: unable to grab read/write lock for reading.",
1003
0
     function );
1004
1005
0
    return( -1 );
1006
0
  }
1007
0
#endif
1008
0
  *offset = internal_logical_volume->current_offset;
1009
1010
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1011
0
  if( libcthreads_read_write_lock_release_for_read(
1012
0
       internal_logical_volume->read_write_lock,
1013
0
       error ) != 1 )
1014
0
  {
1015
0
    libcerror_error_set(
1016
0
     error,
1017
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1018
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1019
0
     "%s: unable to release read/write lock for reading.",
1020
0
     function );
1021
1022
0
    return( -1 );
1023
0
  }
1024
0
#endif
1025
0
  return( 1 );
1026
0
}
1027
1028
/* Retrieves the size
1029
 * Returns 1 if successful or -1 on error
1030
 */
1031
int libvslvm_logical_volume_get_size(
1032
     libvslvm_logical_volume_t *logical_volume,
1033
     size64_t *size,
1034
     libcerror_error_t **error )
1035
0
{
1036
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
1037
0
  static char *function                                       = "libvslvm_logical_volume_get_size";
1038
1039
0
  if( logical_volume == NULL )
1040
0
  {
1041
0
    libcerror_error_set(
1042
0
     error,
1043
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1044
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1045
0
     "%s: invalid logical volume.",
1046
0
     function );
1047
1048
0
    return( -1 );
1049
0
  }
1050
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
1051
1052
0
  if( size == NULL )
1053
0
  {
1054
0
    libcerror_error_set(
1055
0
     error,
1056
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1057
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1058
0
     "%s: invalid size.",
1059
0
     function );
1060
1061
0
    return( -1 );
1062
0
  }
1063
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1064
0
  if( libcthreads_read_write_lock_grab_for_read(
1065
0
       internal_logical_volume->read_write_lock,
1066
0
       error ) != 1 )
1067
0
  {
1068
0
    libcerror_error_set(
1069
0
     error,
1070
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1071
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1072
0
     "%s: unable to grab read/write lock for reading.",
1073
0
     function );
1074
1075
0
    return( -1 );
1076
0
  }
1077
0
#endif
1078
0
  *size = internal_logical_volume->size;
1079
1080
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1081
0
  if( libcthreads_read_write_lock_release_for_read(
1082
0
       internal_logical_volume->read_write_lock,
1083
0
       error ) != 1 )
1084
0
  {
1085
0
    libcerror_error_set(
1086
0
     error,
1087
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1088
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1089
0
     "%s: unable to release read/write lock for reading.",
1090
0
     function );
1091
1092
0
    return( -1 );
1093
0
  }
1094
0
#endif
1095
0
  return( 1 );
1096
0
}
1097
1098
/* Retrieves the size of the ASCII formatted name
1099
 * Returns 1 if successful or -1 on error
1100
 */
1101
int libvslvm_logical_volume_get_name_size(
1102
     libvslvm_logical_volume_t *logical_volume,
1103
     size_t *name_size,
1104
     libcerror_error_t **error )
1105
0
{
1106
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
1107
0
  static char *function                                       = "libvslvm_logical_volume_get_name_size";
1108
0
  int result                                                  = 1;
1109
1110
0
  if( logical_volume == NULL )
1111
0
  {
1112
0
    libcerror_error_set(
1113
0
     error,
1114
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1115
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1116
0
     "%s: invalid logical volume.",
1117
0
     function );
1118
1119
0
    return( -1 );
1120
0
  }
1121
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
1122
1123
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1124
0
  if( libcthreads_read_write_lock_grab_for_read(
1125
0
       internal_logical_volume->read_write_lock,
1126
0
       error ) != 1 )
1127
0
  {
1128
0
    libcerror_error_set(
1129
0
     error,
1130
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1131
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1132
0
     "%s: unable to grab read/write lock for reading.",
1133
0
     function );
1134
1135
0
    return( -1 );
1136
0
  }
1137
0
#endif
1138
0
  if( libvslvm_logical_volume_values_get_name_size(
1139
0
       internal_logical_volume->logical_volume_values,
1140
0
       name_size,
1141
0
       error ) != 1 )
1142
0
  {
1143
0
    libcerror_error_set(
1144
0
     error,
1145
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1146
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1147
0
     "%s: unable to retrieve name size.",
1148
0
     function );
1149
1150
0
    result = -1;
1151
0
  }
1152
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1153
0
  if( libcthreads_read_write_lock_release_for_read(
1154
0
       internal_logical_volume->read_write_lock,
1155
0
       error ) != 1 )
1156
0
  {
1157
0
    libcerror_error_set(
1158
0
     error,
1159
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1160
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1161
0
     "%s: unable to release read/write lock for reading.",
1162
0
     function );
1163
1164
0
    return( -1 );
1165
0
  }
1166
0
#endif
1167
0
  return( result );
1168
0
}
1169
1170
/* Retrieves the ASCII formatted name
1171
 * Returns 1 if successful or -1 on error
1172
 */
1173
int libvslvm_logical_volume_get_name(
1174
     libvslvm_logical_volume_t *logical_volume,
1175
     char *name,
1176
     size_t name_size,
1177
     libcerror_error_t **error )
1178
0
{
1179
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
1180
0
  static char *function                                       = "libvslvm_logical_volume_set_name";
1181
0
  int result                                                  = 1;
1182
1183
0
  if( logical_volume == NULL )
1184
0
  {
1185
0
    libcerror_error_set(
1186
0
     error,
1187
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1188
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1189
0
     "%s: invalid logical volume.",
1190
0
     function );
1191
1192
0
    return( -1 );
1193
0
  }
1194
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
1195
1196
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1197
0
  if( libcthreads_read_write_lock_grab_for_read(
1198
0
       internal_logical_volume->read_write_lock,
1199
0
       error ) != 1 )
1200
0
  {
1201
0
    libcerror_error_set(
1202
0
     error,
1203
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1204
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1205
0
     "%s: unable to grab read/write lock for reading.",
1206
0
     function );
1207
1208
0
    return( -1 );
1209
0
  }
1210
0
#endif
1211
0
  if( libvslvm_logical_volume_values_get_name(
1212
0
       internal_logical_volume->logical_volume_values,
1213
0
       name,
1214
0
       name_size,
1215
0
       error ) != 1 )
1216
0
  {
1217
0
    libcerror_error_set(
1218
0
     error,
1219
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1220
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1221
0
     "%s: unable to retrieve name.",
1222
0
     function );
1223
1224
0
    result = -1;
1225
0
  }
1226
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1227
0
  if( libcthreads_read_write_lock_release_for_read(
1228
0
       internal_logical_volume->read_write_lock,
1229
0
       error ) != 1 )
1230
0
  {
1231
0
    libcerror_error_set(
1232
0
     error,
1233
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1234
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1235
0
     "%s: unable to release read/write lock for reading.",
1236
0
     function );
1237
1238
0
    return( -1 );
1239
0
  }
1240
0
#endif
1241
0
  return( result );
1242
0
}
1243
1244
/* Retrieves the size of the ASCII formatted identifier
1245
 * Returns 1 if successful or -1 on error
1246
 */
1247
int libvslvm_logical_volume_get_identifier_size(
1248
     libvslvm_logical_volume_t *logical_volume,
1249
     size_t *identifier_size,
1250
     libcerror_error_t **error )
1251
0
{
1252
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
1253
0
  static char *function                                       = "libvslvm_logical_volume_get_identifier_size";
1254
0
  int result                                                  = 1;
1255
1256
0
  if( logical_volume == NULL )
1257
0
  {
1258
0
    libcerror_error_set(
1259
0
     error,
1260
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1261
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1262
0
     "%s: invalid logicalogical.",
1263
0
     function );
1264
1265
0
    return( -1 );
1266
0
  }
1267
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
1268
1269
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1270
0
  if( libcthreads_read_write_lock_grab_for_read(
1271
0
       internal_logical_volume->read_write_lock,
1272
0
       error ) != 1 )
1273
0
  {
1274
0
    libcerror_error_set(
1275
0
     error,
1276
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1277
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1278
0
     "%s: unable to grab read/write lock for reading.",
1279
0
     function );
1280
1281
0
    return( -1 );
1282
0
  }
1283
0
#endif
1284
0
  if( libvslvm_logical_volume_values_get_identifier_size(
1285
0
       internal_logical_volume->logical_volume_values,
1286
0
       identifier_size,
1287
0
       error ) != 1 )
1288
0
  {
1289
0
    libcerror_error_set(
1290
0
     error,
1291
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1292
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1293
0
     "%s: unable to retrieve identifier size.",
1294
0
     function );
1295
1296
0
    result = -1;
1297
0
  }
1298
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1299
0
  if( libcthreads_read_write_lock_release_for_read(
1300
0
       internal_logical_volume->read_write_lock,
1301
0
       error ) != 1 )
1302
0
  {
1303
0
    libcerror_error_set(
1304
0
     error,
1305
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1306
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1307
0
     "%s: unable to release read/write lock for reading.",
1308
0
     function );
1309
1310
0
    return( -1 );
1311
0
  }
1312
0
#endif
1313
0
  return( result );
1314
0
}
1315
1316
/* Retrieves the ASCII formatted identifier
1317
 * Returns 1 if successful or -1 on error
1318
 */
1319
int libvslvm_logical_volume_get_identifier(
1320
     libvslvm_logical_volume_t *logical_volume,
1321
     char *identifier,
1322
     size_t identifier_size,
1323
     libcerror_error_t **error )
1324
0
{
1325
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
1326
0
  static char *function                                       = "libvslvm_logical_volume_set_identifier";
1327
0
  int result                                                  = 1;
1328
1329
0
  if( logical_volume == NULL )
1330
0
  {
1331
0
    libcerror_error_set(
1332
0
     error,
1333
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1334
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1335
0
     "%s: invalid logical volume.",
1336
0
     function );
1337
1338
0
    return( -1 );
1339
0
  }
1340
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
1341
1342
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1343
0
  if( libcthreads_read_write_lock_grab_for_read(
1344
0
       internal_logical_volume->read_write_lock,
1345
0
       error ) != 1 )
1346
0
  {
1347
0
    libcerror_error_set(
1348
0
     error,
1349
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1350
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1351
0
     "%s: unable to grab read/write lock for reading.",
1352
0
     function );
1353
1354
0
    return( -1 );
1355
0
  }
1356
0
#endif
1357
0
  if( libvslvm_logical_volume_values_get_identifier(
1358
0
       internal_logical_volume->logical_volume_values,
1359
0
       identifier,
1360
0
       identifier_size,
1361
0
       error ) != 1 )
1362
0
  {
1363
0
    libcerror_error_set(
1364
0
     error,
1365
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1366
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1367
0
     "%s: unable to retrieve identifier.",
1368
0
     function );
1369
1370
0
    result = -1;
1371
0
  }
1372
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1373
0
  if( libcthreads_read_write_lock_release_for_read(
1374
0
       internal_logical_volume->read_write_lock,
1375
0
       error ) != 1 )
1376
0
  {
1377
0
    libcerror_error_set(
1378
0
     error,
1379
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1380
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1381
0
     "%s: unable to release read/write lock for reading.",
1382
0
     function );
1383
1384
0
    return( -1 );
1385
0
  }
1386
0
#endif
1387
0
  return( result );
1388
0
}
1389
1390
/* Retrieves the number of segments
1391
 * Returns 1 if successful or -1 on error
1392
 */
1393
int libvslvm_logical_volume_get_number_of_segments(
1394
     libvslvm_logical_volume_t *logical_volume,
1395
     int *number_of_segments,
1396
     libcerror_error_t **error )
1397
0
{
1398
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
1399
0
  static char *function                                       = "libvslvm_logical_volume_get_number_of_segments";
1400
0
  int result                                                  = 1;
1401
1402
0
  if( logical_volume == NULL )
1403
0
  {
1404
0
    libcerror_error_set(
1405
0
     error,
1406
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1407
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1408
0
     "%s: invalid logical volume.",
1409
0
     function );
1410
1411
0
    return( -1 );
1412
0
  }
1413
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
1414
1415
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1416
0
  if( libcthreads_read_write_lock_grab_for_read(
1417
0
       internal_logical_volume->read_write_lock,
1418
0
       error ) != 1 )
1419
0
  {
1420
0
    libcerror_error_set(
1421
0
     error,
1422
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1423
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1424
0
     "%s: unable to grab read/write lock for reading.",
1425
0
     function );
1426
1427
0
    return( -1 );
1428
0
  }
1429
0
#endif
1430
0
  if( libvslvm_logical_volume_values_get_number_of_segments(
1431
0
       internal_logical_volume->logical_volume_values,
1432
0
       number_of_segments,
1433
0
       error ) != 1 )
1434
0
  {
1435
0
    libcerror_error_set(
1436
0
     error,
1437
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1438
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1439
0
     "%s: unable to retrieve number of segments.",
1440
0
     function );
1441
1442
0
    result = -1;
1443
0
  }
1444
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1445
0
  if( libcthreads_read_write_lock_release_for_read(
1446
0
       internal_logical_volume->read_write_lock,
1447
0
       error ) != 1 )
1448
0
  {
1449
0
    libcerror_error_set(
1450
0
     error,
1451
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1452
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1453
0
     "%s: unable to release read/write lock for reading.",
1454
0
     function );
1455
1456
0
    return( -1 );
1457
0
  }
1458
0
#endif
1459
0
  return( result );
1460
0
}
1461
1462
/* Retrieves a specific segment
1463
 * Returns 1 if successful or -1 on error
1464
 */
1465
int libvslvm_logical_volume_get_segment(
1466
     libvslvm_logical_volume_t *logical_volume,
1467
     int segment_index,
1468
     libvslvm_segment_t **segment,
1469
     libcerror_error_t **error )
1470
0
{
1471
0
  libvslvm_internal_logical_volume_t *internal_logical_volume = NULL;
1472
0
  static char *function                                       = "libvslvm_logical_volume_get_segment";
1473
0
  int result                                                  = 1;
1474
1475
0
  if( logical_volume == NULL )
1476
0
  {
1477
0
    libcerror_error_set(
1478
0
     error,
1479
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1480
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1481
0
     "%s: invalid logical volume.",
1482
0
     function );
1483
1484
0
    return( -1 );
1485
0
  }
1486
0
  internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume;
1487
1488
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1489
0
  if( libcthreads_read_write_lock_grab_for_read(
1490
0
       internal_logical_volume->read_write_lock,
1491
0
       error ) != 1 )
1492
0
  {
1493
0
    libcerror_error_set(
1494
0
     error,
1495
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1496
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1497
0
     "%s: unable to grab read/write lock for reading.",
1498
0
     function );
1499
1500
0
    return( -1 );
1501
0
  }
1502
0
#endif
1503
0
  if( libvslvm_logical_volume_values_get_segment(
1504
0
       internal_logical_volume->logical_volume_values,
1505
0
       segment_index,
1506
0
       segment,
1507
0
       error ) != 1 )
1508
0
  {
1509
0
    libcerror_error_set(
1510
0
     error,
1511
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1512
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1513
0
     "%s: unable to retrieve segment: %d.",
1514
0
     function,
1515
0
     segment_index );
1516
1517
0
    result = -1;
1518
0
  }
1519
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1520
0
  if( libcthreads_read_write_lock_release_for_read(
1521
0
       internal_logical_volume->read_write_lock,
1522
0
       error ) != 1 )
1523
0
  {
1524
0
    libcerror_error_set(
1525
0
     error,
1526
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1527
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1528
0
     "%s: unable to release read/write lock for reading.",
1529
0
     function );
1530
1531
0
    return( -1 );
1532
0
  }
1533
0
#endif
1534
0
  return( result );
1535
0
}
1536
1537
/* Reads chunk data
1538
 * Callback function for the chunk data vector
1539
 * Returns 1 if successful or -1 on error
1540
 */
1541
int libvslvm_logical_volume_read_chunk_data(
1542
     intptr_t *data_handle LIBVSLVM_ATTRIBUTE_UNUSED,
1543
     libbfio_pool_t *file_io_pool,
1544
     libfdata_vector_t *vector,
1545
     libfdata_cache_t *cache,
1546
     int element_index,
1547
     int element_data_file_index,
1548
     off64_t element_data_offset,
1549
     size64_t element_data_size,
1550
     uint32_t element_data_flags LIBVSLVM_ATTRIBUTE_UNUSED,
1551
     uint8_t read_flags LIBVSLVM_ATTRIBUTE_UNUSED,
1552
     libcerror_error_t **error )
1553
0
{
1554
0
  libvslvm_chunk_data_t *chunk_data = NULL;
1555
0
  static char *function             = "libvslvm_logical_volume_read_chunk_data";
1556
1557
0
  LIBVSLVM_UNREFERENCED_PARAMETER( data_handle );
1558
0
  LIBVSLVM_UNREFERENCED_PARAMETER( element_data_flags );
1559
0
  LIBVSLVM_UNREFERENCED_PARAMETER( read_flags );
1560
1561
0
  if( element_data_size > (size64_t) SSIZE_MAX )
1562
0
  {
1563
0
    libcerror_error_set(
1564
0
     error,
1565
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1566
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1567
0
     "%s: invalid element data size value exceeds maximum.",
1568
0
     function );
1569
1570
0
    goto on_error;
1571
0
  }
1572
0
  if( libvslvm_chunk_data_initialize(
1573
0
       &chunk_data,
1574
0
       (size_t) element_data_size,
1575
0
       error ) != 1 )
1576
0
  {
1577
0
    libcerror_error_set(
1578
0
     error,
1579
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1580
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1581
0
     "%s: unable to create chunk data.",
1582
0
     function );
1583
1584
0
    goto on_error;
1585
0
  }
1586
0
  if( libvslvm_chunk_data_read_file_io_pool(
1587
0
       chunk_data,
1588
0
       file_io_pool,
1589
0
       element_data_file_index,
1590
0
             element_data_offset,
1591
0
       error ) != 1 )
1592
0
  {
1593
0
    libcerror_error_set(
1594
0
     error,
1595
0
     LIBCERROR_ERROR_DOMAIN_IO,
1596
0
     LIBCERROR_IO_ERROR_READ_FAILED,
1597
0
     "%s: unable to read chunk data.",
1598
0
     function );
1599
1600
0
    goto on_error;
1601
0
  }
1602
0
  if( libfdata_vector_set_element_value_by_index(
1603
0
       vector,
1604
0
       (intptr_t *) file_io_pool,
1605
0
       cache,
1606
0
       element_index,
1607
0
       (intptr_t *) chunk_data,
1608
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_chunk_data_free,
1609
0
       LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
1610
0
       error ) != 1 )
1611
0
  {
1612
0
    libcerror_error_set(
1613
0
     error,
1614
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1615
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1616
0
     "%s: unable to set chunk data as element value.",
1617
0
     function );
1618
1619
0
    goto on_error;
1620
0
  }
1621
0
  return( 1 );
1622
1623
0
on_error:
1624
0
  if( chunk_data != NULL )
1625
0
  {
1626
0
    libvslvm_chunk_data_free(
1627
0
     &chunk_data,
1628
     NULL );
1629
0
  }
1630
0
  return( -1 );
1631
0
}
1632