Coverage Report

Created: 2026-08-31 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvsmbr/libvsmbr/libvsmbr_partition.c
Line
Count
Source
1
/*
2
 * The partition functions
3
 *
4
 * Copyright (C) 2010-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 <types.h>
25
26
#include "libvsmbr_definitions.h"
27
#include "libvsmbr_io_handle.h"
28
#include "libvsmbr_libbfio.h"
29
#include "libvsmbr_libcerror.h"
30
#include "libvsmbr_libcthreads.h"
31
#include "libvsmbr_libfcache.h"
32
#include "libvsmbr_libfdata.h"
33
#include "libvsmbr_partition.h"
34
#include "libvsmbr_sector_data.h"
35
#include "libvsmbr_types.h"
36
#include "libvsmbr_unused.h"
37
38
/* Creates a partition
39
 * Make sure the value partition is referencing, is set to NULL
40
 * Returns 1 if successful or -1 on error
41
 */
42
int libvsmbr_partition_initialize(
43
     libvsmbr_partition_t **partition,
44
     libvsmbr_io_handle_t *io_handle,
45
     libbfio_handle_t *file_io_handle,
46
     libvsmbr_partition_values_t *partition_values,
47
     libcerror_error_t **error )
48
206
{
49
206
  libvsmbr_internal_partition_t *internal_partition = NULL;
50
206
  static char *function                             = "libvsmbr_partition_initialize";
51
206
  size64_t partition_size                           = 0;
52
206
  off64_t partition_offset                          = 0;
53
206
  int element_index                                 = 0;
54
55
206
  if( partition == NULL )
56
0
  {
57
0
    libcerror_error_set(
58
0
     error,
59
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
60
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
61
0
     "%s: invalid partition.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
206
  if( *partition != NULL )
67
0
  {
68
0
    libcerror_error_set(
69
0
     error,
70
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
71
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
72
0
     "%s: invalid partition value already set.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
206
  if( io_handle == NULL )
78
0
  {
79
0
    libcerror_error_set(
80
0
     error,
81
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
82
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
83
0
     "%s: invalid IO handle.",
84
0
     function );
85
86
0
    return( -1 );
87
0
  }
88
206
  if( partition_values == NULL )
89
0
  {
90
0
    libcerror_error_set(
91
0
     error,
92
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
93
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
94
0
     "%s: invalid partition values.",
95
0
     function );
96
97
0
    return( -1 );
98
0
  }
99
206
  internal_partition = memory_allocate_structure(
100
206
                        libvsmbr_internal_partition_t );
101
102
206
  if( internal_partition == NULL )
103
0
  {
104
0
    libcerror_error_set(
105
0
     error,
106
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
107
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
108
0
     "%s: unable to create partition.",
109
0
     function );
110
111
0
    goto on_error;
112
0
  }
113
206
  if( memory_set(
114
206
       internal_partition,
115
206
       0,
116
206
       sizeof( libvsmbr_internal_partition_t ) ) == NULL )
117
0
  {
118
0
    libcerror_error_set(
119
0
     error,
120
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
121
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
122
0
     "%s: unable to clear partition.",
123
0
     function );
124
125
0
    goto on_error;
126
0
  }
127
206
  if( libvsmbr_partition_values_get_sector_number(
128
206
       partition_values,
129
206
       (uint32_t *) &partition_offset,
130
206
       error ) != 1 )
131
0
  {
132
0
    libcerror_error_set(
133
0
     error,
134
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
135
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
136
0
     "%s: unable to retrieve partition sector number.",
137
0
     function );
138
139
0
    goto on_error;
140
0
  }
141
206
  partition_offset *= io_handle->bytes_per_sector;
142
206
  partition_offset += partition_values->partition_record_offset;
143
144
206
  if( libvsmbr_partition_values_get_number_of_sectors(
145
206
       partition_values,
146
206
       (uint32_t *) &partition_size,
147
206
       error ) != 1 )
148
0
  {
149
0
    libcerror_error_set(
150
0
     error,
151
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
152
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
153
0
     "%s: unable to retrieve partition number of sectors.",
154
0
     function );
155
156
0
    goto on_error;
157
0
  }
158
206
  partition_size *= io_handle->bytes_per_sector;
159
160
206
  if( libfdata_vector_initialize(
161
206
       &( internal_partition->sectors_vector ),
162
206
       io_handle->bytes_per_sector,
163
206
       NULL,
164
206
       NULL,
165
206
       NULL,
166
206
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libvsmbr_partition_read_element_data,
167
206
       NULL,
168
206
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
169
206
       error ) != 1 )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
174
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
175
0
     "%s: unable to create sectors vector.",
176
0
     function );
177
178
0
    goto on_error;
179
0
  }
180
206
  if( libfdata_vector_append_segment(
181
206
       internal_partition->sectors_vector,
182
206
       &element_index,
183
206
       0,
184
206
       partition_offset,
185
206
       partition_size,
186
206
       0,
187
206
       error ) != 1 )
188
0
  {
189
0
    libcerror_error_set(
190
0
     error,
191
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
192
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
193
0
     "%s: unable to append segment to sectors vector.",
194
0
     function );
195
196
0
    goto on_error;
197
0
  }
198
206
  if( libfcache_cache_initialize(
199
206
       &( internal_partition->sectors_cache ),
200
206
       LIBVSMBR_MAXIMUM_CACHE_ENTRIES_SECTORS,
201
206
       error ) != 1 )
202
0
  {
203
0
    libcerror_error_set(
204
0
     error,
205
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
206
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
207
0
     "%s: unable to create sectors cache.",
208
0
     function );
209
210
0
    goto on_error;
211
0
  }
212
206
#if defined( HAVE_MULTI_THREAD_SUPPORT )
213
206
  if( libcthreads_read_write_lock_initialize(
214
206
       &( internal_partition->read_write_lock ),
215
206
       error ) != 1 )
216
0
  {
217
0
    libcerror_error_set(
218
0
     error,
219
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
220
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
221
0
     "%s: unable to initialize read/write lock.",
222
0
     function );
223
224
0
    goto on_error;
225
0
  }
226
206
#endif
227
206
  internal_partition->file_io_handle   = file_io_handle;
228
206
  internal_partition->partition_values = partition_values;
229
206
  internal_partition->offset           = partition_offset;
230
206
  internal_partition->size             = partition_size;
231
232
206
  *partition = (libvsmbr_partition_t *) internal_partition;
233
234
206
  return( 1 );
235
236
0
on_error:
237
0
  if( internal_partition != NULL )
238
0
  {
239
0
    memory_free(
240
0
     internal_partition );
241
0
  }
242
0
  return( -1 );
243
206
}
244
245
/* Frees a partition
246
 * Returns 1 if successful or -1 on error
247
 */
248
int libvsmbr_partition_free(
249
     libvsmbr_partition_t **partition,
250
     libcerror_error_t **error )
251
206
{
252
206
  libvsmbr_internal_partition_t *internal_partition = NULL;
253
206
  static char *function                             = "libvsmbr_partition_free";
254
206
  int result                                        = 1;
255
256
206
  if( partition == NULL )
257
0
  {
258
0
    libcerror_error_set(
259
0
     error,
260
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
261
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
262
0
     "%s: invalid partition.",
263
0
     function );
264
265
0
    return( -1 );
266
0
  }
267
206
  if( *partition != NULL )
268
206
  {
269
206
    internal_partition = (libvsmbr_internal_partition_t *) *partition;
270
206
    *partition         = NULL;
271
272
    /* The file_io_handle and partition_values references are freed elsewhere
273
     */
274
206
    if( libfdata_vector_free(
275
206
         &( internal_partition->sectors_vector ),
276
206
         error ) != 1 )
277
0
    {
278
0
      libcerror_error_set(
279
0
       error,
280
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
281
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
282
0
       "%s: unable to free sectors vector.",
283
0
       function );
284
285
0
      result = -1;
286
0
    }
287
206
    if( libfcache_cache_free(
288
206
         &( internal_partition->sectors_cache ),
289
206
         error ) != 1 )
290
0
    {
291
0
      libcerror_error_set(
292
0
       error,
293
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
294
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
295
0
       "%s: unable to free sectors cache.",
296
0
       function );
297
298
0
      result = -1;
299
0
    }
300
206
#if defined( HAVE_MULTI_THREAD_SUPPORT )
301
206
    if( libcthreads_read_write_lock_free(
302
206
         &( internal_partition->read_write_lock ),
303
206
         error ) != 1 )
304
0
    {
305
0
      libcerror_error_set(
306
0
       error,
307
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
308
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
309
0
       "%s: unable to free read/write lock.",
310
0
       function );
311
312
0
      result = -1;
313
0
    }
314
206
#endif
315
206
    memory_free(
316
206
     internal_partition );
317
206
  }
318
206
  return( result );
319
206
}
320
321
/* Retrieves the partition type
322
 * Returns 1 if successful or -1 on error
323
 */
324
int libvsmbr_partition_get_type(
325
     libvsmbr_partition_t *partition,
326
     uint8_t *type,
327
     libcerror_error_t **error )
328
206
{
329
206
  libvsmbr_internal_partition_t *internal_partition = NULL;
330
206
  static char *function                             = "libvsmbr_partition_get_type";
331
206
  int result                                        = 1;
332
333
206
  if( partition == NULL )
334
0
  {
335
0
    libcerror_error_set(
336
0
     error,
337
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
338
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
339
0
     "%s: invalid partition.",
340
0
     function );
341
342
0
    return( -1 );
343
0
  }
344
206
  internal_partition = (libvsmbr_internal_partition_t *) partition;
345
346
206
#if defined( HAVE_MULTI_THREAD_SUPPORT )
347
206
  if( libcthreads_read_write_lock_grab_for_read(
348
206
       internal_partition->read_write_lock,
349
206
       error ) != 1 )
350
0
  {
351
0
    libcerror_error_set(
352
0
     error,
353
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
354
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
355
0
     "%s: unable to grab read/write lock for reading.",
356
0
     function );
357
358
0
    return( -1 );
359
0
  }
360
206
#endif
361
206
  if( libvsmbr_partition_values_get_type(
362
206
       internal_partition->partition_values,
363
206
       type,
364
206
       error ) != 1 )
365
0
  {
366
0
    libcerror_error_set(
367
0
     error,
368
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
369
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
370
0
     "%s: unable to retrieve type.",
371
0
     function );
372
373
0
    result = -1;
374
0
  }
375
206
#if defined( HAVE_MULTI_THREAD_SUPPORT )
376
206
  if( libcthreads_read_write_lock_release_for_read(
377
206
       internal_partition->read_write_lock,
378
206
       error ) != 1 )
379
0
  {
380
0
    libcerror_error_set(
381
0
     error,
382
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
383
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
384
0
     "%s: unable to release read/write lock for reading.",
385
0
     function );
386
387
0
    return( -1 );
388
0
  }
389
206
#endif
390
206
  return( result );
391
206
}
392
393
/* Retrieves the partition offset relative to the start of the volume
394
 * Returns 1 if successful or -1 on error
395
 */
396
int libvsmbr_partition_get_volume_offset(
397
     libvsmbr_partition_t *partition,
398
     off64_t *volume_offset,
399
     libcerror_error_t **error )
400
206
{
401
206
  libvsmbr_internal_partition_t *internal_partition = NULL;
402
206
  static char *function                             = "libvsmbr_partition_get_volume_offset";
403
404
206
  if( partition == NULL )
405
0
  {
406
0
    libcerror_error_set(
407
0
     error,
408
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
409
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
410
0
     "%s: invalid partition.",
411
0
     function );
412
413
0
    return( -1 );
414
0
  }
415
206
  internal_partition = (libvsmbr_internal_partition_t *) partition;
416
417
206
  if( volume_offset == NULL )
418
0
  {
419
0
    libcerror_error_set(
420
0
     error,
421
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
422
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
423
0
     "%s: invalid volume offset.",
424
0
     function );
425
426
0
    return( -1 );
427
0
  }
428
206
#if defined( HAVE_MULTI_THREAD_SUPPORT )
429
206
  if( libcthreads_read_write_lock_grab_for_read(
430
206
       internal_partition->read_write_lock,
431
206
       error ) != 1 )
432
0
  {
433
0
    libcerror_error_set(
434
0
     error,
435
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
436
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
437
0
     "%s: unable to grab read/write lock for reading.",
438
0
     function );
439
440
0
    return( -1 );
441
0
  }
442
206
#endif
443
206
  *volume_offset = internal_partition->offset;
444
445
206
#if defined( HAVE_MULTI_THREAD_SUPPORT )
446
206
  if( libcthreads_read_write_lock_release_for_read(
447
206
       internal_partition->read_write_lock,
448
206
       error ) != 1 )
449
0
  {
450
0
    libcerror_error_set(
451
0
     error,
452
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
453
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
454
0
     "%s: unable to release read/write lock for reading.",
455
0
     function );
456
457
0
    return( -1 );
458
0
  }
459
206
#endif
460
206
  return( 1 );
461
206
}
462
463
/* Reads (partition) data at the current offset into a buffer using a Basic File IO (bfio) handle
464
 * This function is not multi-thread safe acquire write lock before call
465
 * Returns the number of bytes read or -1 on error
466
 */
467
ssize_t libvsmbr_internal_partition_read_buffer_from_file_io_handle(
468
         libvsmbr_internal_partition_t *internal_partition,
469
         libbfio_handle_t *file_io_handle,
470
         void *buffer,
471
         size_t buffer_size,
472
         libcerror_error_t **error )
473
5.08k
{
474
5.08k
  libvsmbr_sector_data_t *sector_data = NULL;
475
5.08k
  static char *function               = "libvsmbr_internal_partition_read_buffer_from_file_io_handle";
476
5.08k
  off64_t current_offset              = 0;
477
5.08k
  off64_t element_data_offset         = 0;
478
5.08k
  size_t buffer_offset                = 0;
479
5.08k
  size_t read_size                    = 0;
480
481
5.08k
  if( internal_partition == NULL )
482
0
  {
483
0
    libcerror_error_set(
484
0
     error,
485
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
486
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
487
0
     "%s: invalid partition.",
488
0
     function );
489
490
0
    return( -1 );
491
0
  }
492
5.08k
  if( internal_partition->current_offset < 0 )
493
0
  {
494
0
    libcerror_error_set(
495
0
     error,
496
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
497
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
498
0
     "%s: invalid partition - current offset value out of bounds.",
499
0
     function );
500
501
0
    return( -1 );
502
0
  }
503
5.08k
  if( buffer == NULL )
504
0
  {
505
0
    libcerror_error_set(
506
0
     error,
507
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
508
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
509
0
     "%s: invalid buffer.",
510
0
     function );
511
512
0
    return( -1 );
513
0
  }
514
5.08k
  if( buffer_size > (size_t) SSIZE_MAX )
515
0
  {
516
0
    libcerror_error_set(
517
0
     error,
518
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
519
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
520
0
     "%s: invalid buffer size value exceeds maximum.",
521
0
     function );
522
523
0
    return( -1 );
524
0
  }
525
5.08k
  if( buffer_size == 0 )
526
0
  {
527
0
    return( 0 );
528
0
  }
529
5.08k
  if( (size64_t) internal_partition->current_offset >= internal_partition->size )
530
0
  {
531
0
    return( 0 );
532
0
  }
533
5.08k
  if( (size64_t) buffer_size > ( internal_partition->size - internal_partition->current_offset ) )
534
16
  {
535
16
    buffer_size = (size_t) ( internal_partition->size - internal_partition->current_offset );
536
16
  }
537
5.08k
  current_offset = internal_partition->current_offset;
538
539
13.7k
  while( buffer_size > 0 )
540
8.87k
  {
541
8.87k
    if( libfdata_vector_get_element_value_at_offset(
542
8.87k
         internal_partition->sectors_vector,
543
8.87k
         (intptr_t *) file_io_handle,
544
8.87k
         (libfdata_cache_t *) internal_partition->sectors_cache,
545
8.87k
         current_offset,
546
8.87k
         &element_data_offset,
547
8.87k
         (intptr_t **) &sector_data,
548
8.87k
         0,
549
8.87k
         error ) != 1 )
550
180
    {
551
180
      libcerror_error_set(
552
180
       error,
553
180
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
554
180
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
555
180
       "%s: unable to retrieve sector data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
556
180
       function,
557
180
       current_offset,
558
180
       current_offset );
559
560
180
      return( -1 );
561
180
    }
562
8.69k
    if( sector_data == NULL )
563
0
    {
564
0
      libcerror_error_set(
565
0
       error,
566
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
567
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
568
0
       "%s: missing sector data.",
569
0
       function );
570
571
0
      return( -1 );
572
0
    }
573
8.69k
    read_size = sector_data->data_size - (size_t) element_data_offset;
574
575
8.69k
    if( buffer_size < read_size )
576
4.88k
    {
577
4.88k
      read_size = buffer_size;
578
4.88k
    }
579
8.69k
    if( memory_copy(
580
8.69k
         &( ( (uint8_t *) buffer )[ buffer_offset ] ),
581
8.69k
         &( sector_data->data[ element_data_offset ] ),
582
8.69k
         read_size ) == NULL )
583
0
    {
584
0
      libcerror_error_set(
585
0
       error,
586
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
587
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
588
0
       "%s: unable to copy sector data.",
589
0
       function );
590
591
0
      return( -1 );
592
0
    }
593
8.69k
    current_offset += read_size;
594
8.69k
    buffer_offset  += read_size;
595
8.69k
    buffer_size    -= read_size;
596
8.69k
  }
597
4.90k
  internal_partition->current_offset = current_offset;
598
599
4.90k
  return( (ssize_t) buffer_offset );
600
5.08k
}
601
602
/* Reads (partition) data at the current offset into a buffer
603
 * Returns the number of bytes read or -1 on error
604
 */
605
ssize_t libvsmbr_partition_read_buffer(
606
         libvsmbr_partition_t *partition,
607
         void *buffer,
608
         size_t buffer_size,
609
         libcerror_error_t **error )
610
0
{
611
0
  libvsmbr_internal_partition_t *internal_partition = NULL;
612
0
  static char *function                             = "libvsmbr_partition_read_buffer";
613
0
  ssize_t read_count                                = 0;
614
615
0
  if( partition == NULL )
616
0
  {
617
0
    libcerror_error_set(
618
0
     error,
619
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
620
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
621
0
     "%s: invalid partition.",
622
0
     function );
623
624
0
    return( -1 );
625
0
  }
626
0
  internal_partition = (libvsmbr_internal_partition_t *) partition;
627
628
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
629
0
  if( libcthreads_read_write_lock_grab_for_write(
630
0
       internal_partition->read_write_lock,
631
0
       error ) != 1 )
632
0
  {
633
0
    libcerror_error_set(
634
0
     error,
635
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
636
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
637
0
     "%s: unable to grab read/write lock for writing.",
638
0
     function );
639
640
0
    return( -1 );
641
0
  }
642
0
#endif
643
0
  read_count = libvsmbr_internal_partition_read_buffer_from_file_io_handle(
644
0
          internal_partition,
645
0
          internal_partition->file_io_handle,
646
0
          buffer,
647
0
          buffer_size,
648
0
          error );
649
650
0
  if( read_count == -1 )
651
0
  {
652
0
    libcerror_error_set(
653
0
     error,
654
0
     LIBCERROR_ERROR_DOMAIN_IO,
655
0
     LIBCERROR_IO_ERROR_READ_FAILED,
656
0
     "%s: unable to read buffer from partition.",
657
0
     function );
658
659
0
    read_count = -1;
660
0
  }
661
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
662
0
  if( libcthreads_read_write_lock_release_for_write(
663
0
       internal_partition->read_write_lock,
664
0
       error ) != 1 )
665
0
  {
666
0
    libcerror_error_set(
667
0
     error,
668
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
669
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
670
0
     "%s: unable to release read/write lock for writing.",
671
0
     function );
672
673
0
    return( -1 );
674
0
  }
675
0
#endif
676
0
  return( read_count );
677
0
}
678
679
/* Reads (partition) data at a specific offset
680
 * Returns the number of bytes read or -1 on error
681
 */
682
ssize_t libvsmbr_partition_read_buffer_at_offset(
683
         libvsmbr_partition_t *partition,
684
         void *buffer,
685
         size_t buffer_size,
686
         off64_t offset,
687
         libcerror_error_t **error )
688
5.08k
{
689
5.08k
  libvsmbr_internal_partition_t *internal_partition = NULL;
690
5.08k
  static char *function                             = "libvsmbr_partition_read_buffer_at_offset";
691
5.08k
  ssize_t read_count                                = 0;
692
693
5.08k
  if( partition == NULL )
694
0
  {
695
0
    libcerror_error_set(
696
0
     error,
697
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
698
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
699
0
     "%s: invalid partition.",
700
0
     function );
701
702
0
    return( -1 );
703
0
  }
704
5.08k
  internal_partition = (libvsmbr_internal_partition_t *) partition;
705
706
5.08k
#if defined( HAVE_MULTI_THREAD_SUPPORT )
707
5.08k
  if( libcthreads_read_write_lock_grab_for_write(
708
5.08k
       internal_partition->read_write_lock,
709
5.08k
       error ) != 1 )
710
0
  {
711
0
    libcerror_error_set(
712
0
     error,
713
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
714
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
715
0
     "%s: unable to grab read/write lock for writing.",
716
0
     function );
717
718
0
    return( -1 );
719
0
  }
720
5.08k
#endif
721
5.08k
  if( libvsmbr_internal_partition_seek_offset(
722
5.08k
       internal_partition,
723
5.08k
       offset,
724
5.08k
       SEEK_SET,
725
5.08k
       error ) == -1 )
726
0
  {
727
0
    libcerror_error_set(
728
0
     error,
729
0
     LIBCERROR_ERROR_DOMAIN_IO,
730
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
731
0
     "%s: unable to seek offset.",
732
0
     function );
733
734
0
    goto on_error;
735
0
  }
736
5.08k
  read_count = libvsmbr_internal_partition_read_buffer_from_file_io_handle(
737
5.08k
          internal_partition,
738
5.08k
          internal_partition->file_io_handle,
739
5.08k
          buffer,
740
5.08k
          buffer_size,
741
5.08k
          error );
742
743
5.08k
  if( read_count == -1 )
744
180
  {
745
180
    libcerror_error_set(
746
180
     error,
747
180
     LIBCERROR_ERROR_DOMAIN_IO,
748
180
     LIBCERROR_IO_ERROR_READ_FAILED,
749
180
     "%s: unable to read buffer.",
750
180
     function );
751
752
180
    goto on_error;
753
180
  }
754
4.90k
#if defined( HAVE_MULTI_THREAD_SUPPORT )
755
4.90k
  if( libcthreads_read_write_lock_release_for_write(
756
4.90k
       internal_partition->read_write_lock,
757
4.90k
       error ) != 1 )
758
0
  {
759
0
    libcerror_error_set(
760
0
     error,
761
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
762
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
763
0
     "%s: unable to release read/write lock for writing.",
764
0
     function );
765
766
0
    return( -1 );
767
0
  }
768
4.90k
#endif
769
4.90k
  return( read_count );
770
771
180
on_error:
772
180
#if defined( HAVE_MULTI_THREAD_SUPPORT )
773
180
  libcthreads_read_write_lock_release_for_write(
774
180
   internal_partition->read_write_lock,
775
180
   NULL );
776
180
#endif
777
180
  return( -1 );
778
4.90k
}
779
780
/* Seeks a certain offset of the (partition) data
781
 * This function is not multi-thread safe acquire write lock before call
782
 * Returns the offset if seek is successful or -1 on error
783
 */
784
off64_t libvsmbr_internal_partition_seek_offset(
785
         libvsmbr_internal_partition_t *internal_partition,
786
         off64_t offset,
787
         int whence,
788
         libcerror_error_t **error )
789
5.08k
{
790
5.08k
  static char *function = "libvsmbr_internal_partition_seek_offset";
791
792
5.08k
  if( internal_partition == 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 partition.",
799
0
     function );
800
801
0
    return( -1 );
802
0
  }
803
5.08k
  if( ( whence != SEEK_CUR )
804
5.08k
   && ( whence != SEEK_END )
805
5.08k
   && ( whence != SEEK_SET ) )
806
0
  {
807
0
    libcerror_error_set(
808
0
     error,
809
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
810
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
811
0
     "%s: unsupported whence.",
812
0
     function );
813
814
0
    return( -1 );
815
0
  }
816
5.08k
  if( whence == SEEK_CUR )
817
0
  {
818
0
    offset += internal_partition->current_offset;
819
0
  }
820
5.08k
  else if( whence == SEEK_END )
821
0
  {
822
0
    offset += (off64_t) internal_partition->size;
823
0
  }
824
5.08k
  if( offset < 0 )
825
0
  {
826
0
    libcerror_error_set(
827
0
     error,
828
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
829
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
830
0
     "%s: invalid offset value out of bounds.",
831
0
     function );
832
833
0
    return( -1 );
834
0
  }
835
5.08k
  internal_partition->current_offset = offset;
836
837
5.08k
  return( offset );
838
5.08k
}
839
840
/* Seeks a certain offset of the (partition) data
841
 * Returns the offset if seek is successful or -1 on error
842
 */
843
off64_t libvsmbr_partition_seek_offset(
844
         libvsmbr_partition_t *partition,
845
         off64_t offset,
846
         int whence,
847
         libcerror_error_t **error )
848
0
{
849
0
  libvsmbr_internal_partition_t *internal_partition = NULL;
850
0
  static char *function                             = "libvsmbr_partition_seek_offset";
851
852
0
  if( partition == NULL )
853
0
  {
854
0
    libcerror_error_set(
855
0
     error,
856
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
857
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
858
0
     "%s: invalid partition.",
859
0
     function );
860
861
0
    return( -1 );
862
0
  }
863
0
  internal_partition = (libvsmbr_internal_partition_t *) partition;
864
865
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
866
0
  if( libcthreads_read_write_lock_grab_for_write(
867
0
       internal_partition->read_write_lock,
868
0
       error ) != 1 )
869
0
  {
870
0
    libcerror_error_set(
871
0
     error,
872
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
873
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
874
0
     "%s: unable to grab read/write lock for writing.",
875
0
     function );
876
877
0
    return( -1 );
878
0
  }
879
0
#endif
880
0
  offset = libvsmbr_internal_partition_seek_offset(
881
0
            internal_partition,
882
0
            offset,
883
0
            whence,
884
0
            error );
885
886
0
  if( offset == -1 )
887
0
  {
888
0
    libcerror_error_set(
889
0
     error,
890
0
     LIBCERROR_ERROR_DOMAIN_IO,
891
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
892
0
     "%s: unable to seek offset.",
893
0
     function );
894
895
0
    offset = -1;
896
0
  }
897
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
898
0
  if( libcthreads_read_write_lock_release_for_write(
899
0
       internal_partition->read_write_lock,
900
0
       error ) != 1 )
901
0
  {
902
0
    libcerror_error_set(
903
0
     error,
904
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
905
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
906
0
     "%s: unable to release read/write lock for writing.",
907
0
     function );
908
909
0
    return( -1 );
910
0
  }
911
0
#endif
912
0
  return( offset );
913
0
}
914
915
/* Retrieves the current offset
916
 * Returns 1 if successful or -1 on error
917
 */
918
int libvsmbr_partition_get_offset(
919
     libvsmbr_partition_t *partition,
920
     off64_t *offset,
921
     libcerror_error_t **error )
922
0
{
923
0
  libvsmbr_internal_partition_t *internal_partition = NULL;
924
0
  static char *function                             = "libvsmbr_partition_get_offset";
925
926
0
  if( partition == NULL )
927
0
  {
928
0
    libcerror_error_set(
929
0
     error,
930
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
931
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
932
0
     "%s: invalid partition.",
933
0
     function );
934
935
0
    return( -1 );
936
0
  }
937
0
  internal_partition = (libvsmbr_internal_partition_t *) partition;
938
939
0
  if( offset == NULL )
940
0
  {
941
0
    libcerror_error_set(
942
0
     error,
943
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
944
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
945
0
     "%s: invalid offset.",
946
0
     function );
947
948
0
    return( -1 );
949
0
  }
950
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
951
0
  if( libcthreads_read_write_lock_grab_for_read(
952
0
       internal_partition->read_write_lock,
953
0
       error ) != 1 )
954
0
  {
955
0
    libcerror_error_set(
956
0
     error,
957
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
958
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
959
0
     "%s: unable to grab read/write lock for reading.",
960
0
     function );
961
962
0
    return( -1 );
963
0
  }
964
0
#endif
965
0
  *offset = internal_partition->current_offset;
966
967
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
968
0
  if( libcthreads_read_write_lock_release_for_read(
969
0
       internal_partition->read_write_lock,
970
0
       error ) != 1 )
971
0
  {
972
0
    libcerror_error_set(
973
0
     error,
974
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
975
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
976
0
     "%s: unable to release read/write lock for reading.",
977
0
     function );
978
979
0
    return( -1 );
980
0
  }
981
0
#endif
982
0
  return( 1 );
983
0
}
984
985
/* Retrieves the partition size
986
 * Returns 1 if successful or -1 on error
987
 */
988
int libvsmbr_partition_get_size(
989
     libvsmbr_partition_t *partition,
990
     size64_t *size,
991
     libcerror_error_t **error )
992
206
{
993
206
  libvsmbr_internal_partition_t *internal_partition = NULL;
994
206
  static char *function                             = "libvsmbr_partition_get_size";
995
996
206
  if( partition == NULL )
997
0
  {
998
0
    libcerror_error_set(
999
0
     error,
1000
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1001
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1002
0
     "%s: invalid partition.",
1003
0
     function );
1004
1005
0
    return( -1 );
1006
0
  }
1007
206
  internal_partition = (libvsmbr_internal_partition_t *) partition;
1008
1009
206
  if( size == NULL )
1010
0
  {
1011
0
    libcerror_error_set(
1012
0
     error,
1013
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1014
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1015
0
     "%s: invalid size.",
1016
0
     function );
1017
1018
0
    return( -1 );
1019
0
  }
1020
206
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1021
206
  if( libcthreads_read_write_lock_grab_for_read(
1022
206
       internal_partition->read_write_lock,
1023
206
       error ) != 1 )
1024
0
  {
1025
0
    libcerror_error_set(
1026
0
     error,
1027
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1028
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1029
0
     "%s: unable to grab read/write lock for reading.",
1030
0
     function );
1031
1032
0
    return( -1 );
1033
0
  }
1034
206
#endif
1035
206
  *size = internal_partition->size;
1036
1037
206
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1038
206
  if( libcthreads_read_write_lock_release_for_read(
1039
206
       internal_partition->read_write_lock,
1040
206
       error ) != 1 )
1041
0
  {
1042
0
    libcerror_error_set(
1043
0
     error,
1044
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1045
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1046
0
     "%s: unable to release read/write lock for reading.",
1047
0
     function );
1048
1049
0
    return( -1 );
1050
0
  }
1051
206
#endif
1052
206
  return( 1 );
1053
206
}
1054