Coverage Report

Created: 2023-06-07 06:53

/src/libvsapm/libvsapm/libvsapm_partition.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The partition functions
3
 *
4
 * Copyright (C) 2009-2023, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <types.h>
25
26
#include "libvsapm_definitions.h"
27
#include "libvsapm_io_handle.h"
28
#include "libvsapm_libbfio.h"
29
#include "libvsapm_libcerror.h"
30
#include "libvsapm_libcthreads.h"
31
#include "libvsapm_libfcache.h"
32
#include "libvsapm_libfdata.h"
33
#include "libvsapm_partition.h"
34
#include "libvsapm_partition_map_entry.h"
35
#include "libvsapm_sector_data.h"
36
#include "libvsapm_types.h"
37
#include "libvsapm_unused.h"
38
39
/* Creates a partition
40
 * Make sure the value partition is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libvsapm_partition_initialize(
44
     libvsapm_partition_t **partition,
45
     libvsapm_io_handle_t *io_handle,
46
     libbfio_handle_t *file_io_handle,
47
     libvsapm_partition_map_entry_t *partition_map_entry,
48
     libcerror_error_t **error )
49
45
{
50
45
  libvsapm_internal_partition_t *internal_partition = NULL;
51
45
  static char *function                             = "libvsapm_partition_initialize";
52
45
  size64_t partition_size                           = 0;
53
45
  off64_t partition_offset                          = 0;
54
45
  int element_index                                 = 0;
55
56
45
  if( partition == NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
61
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
62
0
     "%s: invalid partition.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
45
  if( *partition != NULL )
68
0
  {
69
0
    libcerror_error_set(
70
0
     error,
71
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
72
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
73
0
     "%s: invalid partition value already set.",
74
0
     function );
75
76
0
    return( -1 );
77
0
  }
78
45
  if( io_handle == NULL )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
83
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
84
0
     "%s: invalid IO handle.",
85
0
     function );
86
87
0
    return( -1 );
88
0
  }
89
45
  if( partition_map_entry == NULL )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
94
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
95
0
     "%s: invalid partition map entry.",
96
0
     function );
97
98
0
    return( -1 );
99
0
  }
100
45
  internal_partition = memory_allocate_structure(
101
45
                        libvsapm_internal_partition_t );
102
103
45
  if( internal_partition == NULL )
104
0
  {
105
0
    libcerror_error_set(
106
0
     error,
107
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
108
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
109
0
     "%s: unable to create partition.",
110
0
     function );
111
112
0
    goto on_error;
113
0
  }
114
45
  if( memory_set(
115
45
       internal_partition,
116
45
       0,
117
45
       sizeof( libvsapm_internal_partition_t ) ) == NULL )
118
0
  {
119
0
    libcerror_error_set(
120
0
     error,
121
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
122
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
123
0
     "%s: unable to clear partition.",
124
0
     function );
125
126
0
    goto on_error;
127
0
  }
128
45
  if( libvsapm_partition_map_entry_get_sector_number(
129
45
       partition_map_entry,
130
45
       (uint32_t *) &partition_offset,
131
45
       error ) != 1 )
132
0
  {
133
0
    libcerror_error_set(
134
0
     error,
135
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
136
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
137
0
     "%s: unable to retrieve partition sector number.",
138
0
     function );
139
140
0
    goto on_error;
141
0
  }
142
45
  partition_offset *= io_handle->bytes_per_sector;
143
144
45
  if( libvsapm_partition_map_entry_get_number_of_sectors(
145
45
       partition_map_entry,
146
45
       (uint32_t *) &partition_size,
147
45
       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
45
  partition_size *= io_handle->bytes_per_sector;
159
160
45
  if( libfdata_vector_initialize(
161
45
       &( internal_partition->sectors_vector ),
162
45
       io_handle->bytes_per_sector,
163
45
       NULL,
164
45
       NULL,
165
45
       NULL,
166
45
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libvsapm_partition_read_element_data,
167
45
       NULL,
168
45
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
169
45
       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
45
  if( libfdata_vector_append_segment(
181
45
       internal_partition->sectors_vector,
182
45
       &element_index,
183
45
       0,
184
45
       partition_offset,
185
45
       partition_size,
186
45
       0,
187
45
       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
45
  if( libfcache_cache_initialize(
199
45
       &( internal_partition->sectors_cache ),
200
45
       LIBVSAPM_MAXIMUM_CACHE_ENTRIES_SECTORS,
201
45
       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
45
#if defined( HAVE_MULTI_THREAD_SUPPORT )
213
45
  if( libcthreads_read_write_lock_initialize(
214
45
       &( internal_partition->read_write_lock ),
215
45
       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
45
#endif
227
45
  internal_partition->file_io_handle      = file_io_handle;
228
45
  internal_partition->partition_map_entry = partition_map_entry;
229
45
  internal_partition->offset              = partition_offset;
230
45
  internal_partition->size                = partition_size;
231
232
45
  *partition = (libvsapm_partition_t *) internal_partition;
233
234
45
  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
45
}
244
245
/* Frees a partition
246
 * Returns 1 if successful or -1 on error
247
 */
248
int libvsapm_partition_free(
249
     libvsapm_partition_t **partition,
250
     libcerror_error_t **error )
251
45
{
252
45
  libvsapm_internal_partition_t *internal_partition = NULL;
253
45
  static char *function                             = "libvsapm_partition_free";
254
45
  int result                                        = 1;
255
256
45
  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
45
  if( *partition != NULL )
268
45
  {
269
45
    internal_partition = (libvsapm_internal_partition_t *) *partition;
270
45
    *partition         = NULL;
271
272
    /* The file_io_handle and partition_map_entry references are freed elsewhere
273
     */
274
45
    if( libfdata_vector_free(
275
45
         &( internal_partition->sectors_vector ),
276
45
         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
45
    if( libfcache_cache_free(
288
45
         &( internal_partition->sectors_cache ),
289
45
         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
45
#if defined( HAVE_MULTI_THREAD_SUPPORT )
301
45
    if( libcthreads_read_write_lock_free(
302
45
         &( internal_partition->read_write_lock ),
303
45
         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
45
#endif
315
45
    memory_free(
316
45
     internal_partition );
317
45
  }
318
45
  return( result );
319
45
}
320
321
/* Retrieves the ASCII encoded string of the partition name
322
 * Returns 1 if successful or -1 on error
323
 */
324
int libvsapm_partition_get_name_string(
325
     libvsapm_partition_t *partition,
326
     char *string,
327
     size_t string_size,
328
     libcerror_error_t **error )
329
0
{
330
0
  libvsapm_internal_partition_t *internal_partition = NULL;
331
0
  static char *function                             = "libvsapm_partition_get_name_string";
332
0
  int result                                        = 1;
333
334
0
  if( partition == NULL )
335
0
  {
336
0
    libcerror_error_set(
337
0
     error,
338
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
339
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
340
0
     "%s: invalid partition.",
341
0
     function );
342
343
0
    return( -1 );
344
0
  }
345
0
  internal_partition = (libvsapm_internal_partition_t *) partition;
346
347
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
348
0
  if( libcthreads_read_write_lock_grab_for_read(
349
0
       internal_partition->read_write_lock,
350
0
       error ) != 1 )
351
0
  {
352
0
    libcerror_error_set(
353
0
     error,
354
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
355
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
356
0
     "%s: unable to grab read/write lock for reading.",
357
0
     function );
358
359
0
    return( -1 );
360
0
  }
361
0
#endif
362
0
  if( libvsapm_partition_map_entry_get_name_string(
363
0
       internal_partition->partition_map_entry,
364
0
       string,
365
0
       string_size,
366
0
       error ) != 1 )
367
0
  {
368
0
    libcerror_error_set(
369
0
     error,
370
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
371
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
372
0
     "%s: unable to retrieve name string.",
373
0
     function );
374
375
0
    result = -1;
376
0
  }
377
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
378
0
  if( libcthreads_read_write_lock_release_for_read(
379
0
       internal_partition->read_write_lock,
380
0
       error ) != 1 )
381
0
  {
382
0
    libcerror_error_set(
383
0
     error,
384
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
385
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
386
0
     "%s: unable to release read/write lock for reading.",
387
0
     function );
388
389
0
    return( -1 );
390
0
  }
391
0
#endif
392
0
  return( result );
393
0
}
394
395
/* Retrieves the ASCII encoded string of the partition type
396
 * Returns 1 if successful or -1 on error
397
 */
398
int libvsapm_partition_get_type_string(
399
     libvsapm_partition_t *partition,
400
     char *string,
401
     size_t string_size,
402
     libcerror_error_t **error )
403
0
{
404
0
  libvsapm_internal_partition_t *internal_partition = NULL;
405
0
  static char *function                             = "libvsapm_partition_get_type_string";
406
0
  int result                                        = 1;
407
408
0
  if( partition == NULL )
409
0
  {
410
0
    libcerror_error_set(
411
0
     error,
412
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
413
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
414
0
     "%s: invalid partition.",
415
0
     function );
416
417
0
    return( -1 );
418
0
  }
419
0
  internal_partition = (libvsapm_internal_partition_t *) partition;
420
421
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
422
0
  if( libcthreads_read_write_lock_grab_for_read(
423
0
       internal_partition->read_write_lock,
424
0
       error ) != 1 )
425
0
  {
426
0
    libcerror_error_set(
427
0
     error,
428
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
429
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
430
0
     "%s: unable to grab read/write lock for reading.",
431
0
     function );
432
433
0
    return( -1 );
434
0
  }
435
0
#endif
436
0
  if( libvsapm_partition_map_entry_get_type_string(
437
0
       internal_partition->partition_map_entry,
438
0
       string,
439
0
       string_size,
440
0
       error ) != 1 )
441
0
  {
442
0
    libcerror_error_set(
443
0
     error,
444
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
445
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
446
0
     "%s: unable to retrieve type string.",
447
0
     function );
448
449
0
    result = -1;
450
0
  }
451
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
452
0
  if( libcthreads_read_write_lock_release_for_read(
453
0
       internal_partition->read_write_lock,
454
0
       error ) != 1 )
455
0
  {
456
0
    libcerror_error_set(
457
0
     error,
458
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
459
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
460
0
     "%s: unable to release read/write lock for reading.",
461
0
     function );
462
463
0
    return( -1 );
464
0
  }
465
0
#endif
466
0
  return( result );
467
0
}
468
469
/* Retrieves the partition offset relative to the start of the volume
470
 * Returns 1 if successful or -1 on error
471
 */
472
int libvsapm_partition_get_volume_offset(
473
     libvsapm_partition_t *partition,
474
     off64_t *volume_offset,
475
     libcerror_error_t **error )
476
0
{
477
0
  libvsapm_internal_partition_t *internal_partition = NULL;
478
0
  static char *function                             = "libvsapm_partition_get_volume_offset";
479
480
0
  if( partition == NULL )
481
0
  {
482
0
    libcerror_error_set(
483
0
     error,
484
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
485
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
486
0
     "%s: invalid partition.",
487
0
     function );
488
489
0
    return( -1 );
490
0
  }
491
0
  internal_partition = (libvsapm_internal_partition_t *) partition;
492
493
0
  if( volume_offset == NULL )
494
0
  {
495
0
    libcerror_error_set(
496
0
     error,
497
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
498
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
499
0
     "%s: invalid volume offset.",
500
0
     function );
501
502
0
    return( -1 );
503
0
  }
504
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
505
0
  if( libcthreads_read_write_lock_grab_for_read(
506
0
       internal_partition->read_write_lock,
507
0
       error ) != 1 )
508
0
  {
509
0
    libcerror_error_set(
510
0
     error,
511
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
512
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
513
0
     "%s: unable to grab read/write lock for reading.",
514
0
     function );
515
516
0
    return( -1 );
517
0
  }
518
0
#endif
519
0
  *volume_offset = internal_partition->offset;
520
521
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
522
0
  if( libcthreads_read_write_lock_release_for_read(
523
0
       internal_partition->read_write_lock,
524
0
       error ) != 1 )
525
0
  {
526
0
    libcerror_error_set(
527
0
     error,
528
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
529
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
530
0
     "%s: unable to release read/write lock for reading.",
531
0
     function );
532
533
0
    return( -1 );
534
0
  }
535
0
#endif
536
0
  return( 1 );
537
0
}
538
539
/* Retrieves the partition status flags
540
 * Returns 1 if successful or -1 on error
541
 */
542
int libvsapm_partition_get_status_flags(
543
     libvsapm_partition_t *partition,
544
     uint32_t *status_flags,
545
     libcerror_error_t **error )
546
0
{
547
0
  libvsapm_internal_partition_t *internal_partition = NULL;
548
0
  static char *function                             = "libvsapm_partition_get_status_flags";
549
0
  int result                                        = 1;
550
551
0
  if( partition == 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 partition.",
558
0
     function );
559
560
0
    return( -1 );
561
0
  }
562
0
  internal_partition = (libvsapm_internal_partition_t *) partition;
563
564
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
565
0
  if( libcthreads_read_write_lock_grab_for_read(
566
0
       internal_partition->read_write_lock,
567
0
       error ) != 1 )
568
0
  {
569
0
    libcerror_error_set(
570
0
     error,
571
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
572
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
573
0
     "%s: unable to grab read/write lock for reading.",
574
0
     function );
575
576
0
    return( -1 );
577
0
  }
578
0
#endif
579
0
  if( libvsapm_partition_map_entry_get_status_flags(
580
0
       internal_partition->partition_map_entry,
581
0
       status_flags,
582
0
       error ) != 1 )
583
0
  {
584
0
    libcerror_error_set(
585
0
     error,
586
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
587
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
588
0
     "%s: unable to retrieve status flags.",
589
0
     function );
590
591
0
    result = -1;
592
0
  }
593
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
594
0
  if( libcthreads_read_write_lock_release_for_read(
595
0
       internal_partition->read_write_lock,
596
0
       error ) != 1 )
597
0
  {
598
0
    libcerror_error_set(
599
0
     error,
600
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
601
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
602
0
     "%s: unable to release read/write lock for reading.",
603
0
     function );
604
605
0
    return( -1 );
606
0
  }
607
0
#endif
608
0
  return( result );
609
0
}
610
611
/* Reads (partition) data at the current offset into a buffer using a Basic File IO (bfio) handle
612
 * This function is not multi-thread safe acquire write lock before call
613
 * Returns the number of bytes read or -1 on error
614
 */
615
ssize_t libvsapm_internal_partition_read_buffer_from_file_io_handle(
616
         libvsapm_internal_partition_t *internal_partition,
617
         libbfio_handle_t *file_io_handle,
618
         void *buffer,
619
         size_t buffer_size,
620
         libcerror_error_t **error )
621
0
{
622
0
  libvsapm_sector_data_t *sector_data = NULL;
623
0
  static char *function               = "libvsapm_internal_partition_read_buffer_from_file_io_handle";
624
0
  off64_t current_offset              = 0;
625
0
  off64_t element_data_offset         = 0;
626
0
  size_t buffer_offset                = 0;
627
0
  size_t read_size                    = 0;
628
629
0
  if( internal_partition == NULL )
630
0
  {
631
0
    libcerror_error_set(
632
0
     error,
633
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
634
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
635
0
     "%s: invalid partition.",
636
0
     function );
637
638
0
    return( -1 );
639
0
  }
640
0
  if( internal_partition->current_offset < 0 )
641
0
  {
642
0
    libcerror_error_set(
643
0
     error,
644
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
645
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
646
0
     "%s: invalid partition - current offset value out of bounds.",
647
0
     function );
648
649
0
    return( -1 );
650
0
  }
651
0
  if( buffer == NULL )
652
0
  {
653
0
    libcerror_error_set(
654
0
     error,
655
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
656
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
657
0
     "%s: invalid buffer.",
658
0
     function );
659
660
0
    return( -1 );
661
0
  }
662
0
  if( buffer_size > (size_t) SSIZE_MAX )
663
0
  {
664
0
    libcerror_error_set(
665
0
     error,
666
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
667
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
668
0
     "%s: invalid buffer size value exceeds maximum.",
669
0
     function );
670
671
0
    return( -1 );
672
0
  }
673
0
  if( buffer_size == 0 )
674
0
  {
675
0
    return( 0 );
676
0
  }
677
0
  if( (size64_t) internal_partition->current_offset >= internal_partition->size )
678
0
  {
679
0
    return( 0 );
680
0
  }
681
0
  if( (size64_t) buffer_size > ( internal_partition->size - internal_partition->current_offset ) )
682
0
  {
683
0
    buffer_size = (size_t) ( internal_partition->size - internal_partition->current_offset );
684
0
  }
685
0
  current_offset = internal_partition->current_offset;
686
687
0
  while( buffer_size > 0 )
688
0
  {
689
0
    if( libfdata_vector_get_element_value_at_offset(
690
0
         internal_partition->sectors_vector,
691
0
         (intptr_t *) file_io_handle,
692
0
         (libfdata_cache_t *) internal_partition->sectors_cache,
693
0
         current_offset,
694
0
         &element_data_offset,
695
0
         (intptr_t **) &sector_data,
696
0
         0,
697
0
         error ) != 1 )
698
0
    {
699
0
      libcerror_error_set(
700
0
       error,
701
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
702
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
703
0
       "%s: unable to retrieve sector data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
704
0
       function,
705
0
       current_offset,
706
0
       current_offset );
707
708
0
      return( -1 );
709
0
    }
710
0
    if( sector_data == NULL )
711
0
    {
712
0
      libcerror_error_set(
713
0
       error,
714
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
715
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
716
0
       "%s: missing sector data.",
717
0
       function );
718
719
0
      return( -1 );
720
0
    }
721
0
    read_size = sector_data->data_size - (size_t) element_data_offset;
722
723
0
    if( buffer_size < read_size )
724
0
    {
725
0
      read_size = buffer_size;
726
0
    }
727
0
    if( memory_copy(
728
0
         &( ( (uint8_t *) buffer )[ buffer_offset ] ),
729
0
         &( sector_data->data[ element_data_offset ] ),
730
0
         read_size ) == NULL )
731
0
    {
732
0
      libcerror_error_set(
733
0
       error,
734
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
735
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
736
0
       "%s: unable to copy sector data.",
737
0
       function );
738
739
0
      return( -1 );
740
0
    }
741
0
    current_offset += read_size;
742
0
    buffer_offset  += read_size;
743
0
    buffer_size    -= read_size;
744
0
  }
745
0
  internal_partition->current_offset = current_offset;
746
747
0
  return( (ssize_t) buffer_offset );
748
0
}
749
750
/* Reads (partition) data at the current offset into a buffer
751
 * Returns the number of bytes read or -1 on error
752
 */
753
ssize_t libvsapm_partition_read_buffer(
754
         libvsapm_partition_t *partition,
755
         void *buffer,
756
         size_t buffer_size,
757
         libcerror_error_t **error )
758
0
{
759
0
  libvsapm_internal_partition_t *internal_partition = NULL;
760
0
  static char *function                             = "libvsapm_partition_read_buffer";
761
0
  ssize_t read_count                                = 0;
762
763
0
  if( partition == NULL )
764
0
  {
765
0
    libcerror_error_set(
766
0
     error,
767
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
768
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
769
0
     "%s: invalid partition.",
770
0
     function );
771
772
0
    return( -1 );
773
0
  }
774
0
  internal_partition = (libvsapm_internal_partition_t *) partition;
775
776
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
777
0
  if( libcthreads_read_write_lock_grab_for_write(
778
0
       internal_partition->read_write_lock,
779
0
       error ) != 1 )
780
0
  {
781
0
    libcerror_error_set(
782
0
     error,
783
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
784
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
785
0
     "%s: unable to grab read/write lock for writing.",
786
0
     function );
787
788
0
    return( -1 );
789
0
  }
790
0
#endif
791
0
  read_count = libvsapm_internal_partition_read_buffer_from_file_io_handle(
792
0
          internal_partition,
793
0
          internal_partition->file_io_handle,
794
0
          buffer,
795
0
          buffer_size,
796
0
          error );
797
798
0
  if( read_count == -1 )
799
0
  {
800
0
    libcerror_error_set(
801
0
     error,
802
0
     LIBCERROR_ERROR_DOMAIN_IO,
803
0
     LIBCERROR_IO_ERROR_READ_FAILED,
804
0
     "%s: unable to read buffer from partition.",
805
0
     function );
806
807
0
    read_count = -1;
808
0
  }
809
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
810
0
  if( libcthreads_read_write_lock_release_for_write(
811
0
       internal_partition->read_write_lock,
812
0
       error ) != 1 )
813
0
  {
814
0
    libcerror_error_set(
815
0
     error,
816
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
817
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
818
0
     "%s: unable to release read/write lock for writing.",
819
0
     function );
820
821
0
    return( -1 );
822
0
  }
823
0
#endif
824
0
  return( read_count );
825
0
}
826
827
/* Reads (partition) data at a specific offset
828
 * Returns the number of bytes read or -1 on error
829
 */
830
ssize_t libvsapm_partition_read_buffer_at_offset(
831
         libvsapm_partition_t *partition,
832
         void *buffer,
833
         size_t buffer_size,
834
         off64_t offset,
835
         libcerror_error_t **error )
836
0
{
837
0
  libvsapm_internal_partition_t *internal_partition = NULL;
838
0
  static char *function                             = "libvsapm_partition_read_buffer_at_offset";
839
0
  ssize_t read_count                                = 0;
840
841
0
  if( partition == NULL )
842
0
  {
843
0
    libcerror_error_set(
844
0
     error,
845
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
846
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
847
0
     "%s: invalid partition.",
848
0
     function );
849
850
0
    return( -1 );
851
0
  }
852
0
  internal_partition = (libvsapm_internal_partition_t *) partition;
853
854
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
855
0
  if( libcthreads_read_write_lock_grab_for_write(
856
0
       internal_partition->read_write_lock,
857
0
       error ) != 1 )
858
0
  {
859
0
    libcerror_error_set(
860
0
     error,
861
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
862
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
863
0
     "%s: unable to grab read/write lock for writing.",
864
0
     function );
865
866
0
    return( -1 );
867
0
  }
868
0
#endif
869
0
  if( libvsapm_internal_partition_seek_offset(
870
0
       internal_partition,
871
0
       offset,
872
0
       SEEK_SET,
873
0
       error ) == -1 )
874
0
  {
875
0
    libcerror_error_set(
876
0
     error,
877
0
     LIBCERROR_ERROR_DOMAIN_IO,
878
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
879
0
     "%s: unable to seek offset.",
880
0
     function );
881
882
0
    goto on_error;
883
0
  }
884
0
  read_count = libvsapm_internal_partition_read_buffer_from_file_io_handle(
885
0
          internal_partition,
886
0
          internal_partition->file_io_handle,
887
0
          buffer,
888
0
          buffer_size,
889
0
          error );
890
891
0
  if( read_count == -1 )
892
0
  {
893
0
    libcerror_error_set(
894
0
     error,
895
0
     LIBCERROR_ERROR_DOMAIN_IO,
896
0
     LIBCERROR_IO_ERROR_READ_FAILED,
897
0
     "%s: unable to read buffer.",
898
0
     function );
899
900
0
    goto on_error;
901
0
  }
902
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
903
0
  if( libcthreads_read_write_lock_release_for_write(
904
0
       internal_partition->read_write_lock,
905
0
       error ) != 1 )
906
0
  {
907
0
    libcerror_error_set(
908
0
     error,
909
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
910
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
911
0
     "%s: unable to release read/write lock for writing.",
912
0
     function );
913
914
0
    return( -1 );
915
0
  }
916
0
#endif
917
0
  return( read_count );
918
919
0
on_error:
920
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
921
0
  libcthreads_read_write_lock_release_for_write(
922
0
   internal_partition->read_write_lock,
923
0
   NULL );
924
0
#endif
925
0
  return( -1 );
926
0
}
927
928
/* Seeks a certain offset of the (partition) data
929
 * This function is not multi-thread safe acquire write lock before call
930
 * Returns the offset if seek is successful or -1 on error
931
 */
932
off64_t libvsapm_internal_partition_seek_offset(
933
         libvsapm_internal_partition_t *internal_partition,
934
         off64_t offset,
935
         int whence,
936
         libcerror_error_t **error )
937
0
{
938
0
  static char *function = "libvsapm_internal_partition_seek_offset";
939
940
0
  if( internal_partition == NULL )
941
0
  {
942
0
    libcerror_error_set(
943
0
     error,
944
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
945
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
946
0
     "%s: invalid partition.",
947
0
     function );
948
949
0
    return( -1 );
950
0
  }
951
0
  if( ( whence != SEEK_CUR )
952
0
   && ( whence != SEEK_END )
953
0
   && ( whence != SEEK_SET ) )
954
0
  {
955
0
    libcerror_error_set(
956
0
     error,
957
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
958
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
959
0
     "%s: unsupported whence.",
960
0
     function );
961
962
0
    return( -1 );
963
0
  }
964
0
  if( whence == SEEK_CUR )
965
0
  {
966
0
    offset += internal_partition->current_offset;
967
0
  }
968
0
  else if( whence == SEEK_END )
969
0
  {
970
0
    offset += (off64_t) internal_partition->size;
971
0
  }
972
0
  if( offset < 0 )
973
0
  {
974
0
    libcerror_error_set(
975
0
     error,
976
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
977
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
978
0
     "%s: invalid offset value out of bounds.",
979
0
     function );
980
981
0
    return( -1 );
982
0
  }
983
0
  internal_partition->current_offset = offset;
984
985
0
  return( offset );
986
0
}
987
988
/* Seeks a certain offset of the (partition) data
989
 * Returns the offset if seek is successful or -1 on error
990
 */
991
off64_t libvsapm_partition_seek_offset(
992
         libvsapm_partition_t *partition,
993
         off64_t offset,
994
         int whence,
995
         libcerror_error_t **error )
996
0
{
997
0
  libvsapm_internal_partition_t *internal_partition = NULL;
998
0
  static char *function                             = "libvsapm_partition_seek_offset";
999
1000
0
  if( partition == NULL )
1001
0
  {
1002
0
    libcerror_error_set(
1003
0
     error,
1004
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1005
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1006
0
     "%s: invalid partition.",
1007
0
     function );
1008
1009
0
    return( -1 );
1010
0
  }
1011
0
  internal_partition = (libvsapm_internal_partition_t *) partition;
1012
1013
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1014
0
  if( libcthreads_read_write_lock_grab_for_write(
1015
0
       internal_partition->read_write_lock,
1016
0
       error ) != 1 )
1017
0
  {
1018
0
    libcerror_error_set(
1019
0
     error,
1020
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1021
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1022
0
     "%s: unable to grab read/write lock for writing.",
1023
0
     function );
1024
1025
0
    return( -1 );
1026
0
  }
1027
0
#endif
1028
0
  offset = libvsapm_internal_partition_seek_offset(
1029
0
            internal_partition,
1030
0
            offset,
1031
0
            whence,
1032
0
            error );
1033
1034
0
  if( offset == -1 )
1035
0
  {
1036
0
    libcerror_error_set(
1037
0
     error,
1038
0
     LIBCERROR_ERROR_DOMAIN_IO,
1039
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
1040
0
     "%s: unable to seek offset.",
1041
0
     function );
1042
1043
0
    offset = -1;
1044
0
  }
1045
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1046
0
  if( libcthreads_read_write_lock_release_for_write(
1047
0
       internal_partition->read_write_lock,
1048
0
       error ) != 1 )
1049
0
  {
1050
0
    libcerror_error_set(
1051
0
     error,
1052
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1053
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1054
0
     "%s: unable to release read/write lock for writing.",
1055
0
     function );
1056
1057
0
    return( -1 );
1058
0
  }
1059
0
#endif
1060
0
  return( offset );
1061
0
}
1062
1063
/* Retrieves the current offset
1064
 * Returns 1 if successful or -1 on error
1065
 */
1066
int libvsapm_partition_get_offset(
1067
     libvsapm_partition_t *partition,
1068
     off64_t *offset,
1069
     libcerror_error_t **error )
1070
0
{
1071
0
  libvsapm_internal_partition_t *internal_partition = NULL;
1072
0
  static char *function                             = "libvsapm_partition_get_offset";
1073
1074
0
  if( partition == NULL )
1075
0
  {
1076
0
    libcerror_error_set(
1077
0
     error,
1078
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1079
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1080
0
     "%s: invalid partition.",
1081
0
     function );
1082
1083
0
    return( -1 );
1084
0
  }
1085
0
  internal_partition = (libvsapm_internal_partition_t *) partition;
1086
1087
0
  if( offset == NULL )
1088
0
  {
1089
0
    libcerror_error_set(
1090
0
     error,
1091
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1092
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1093
0
     "%s: invalid offset.",
1094
0
     function );
1095
1096
0
    return( -1 );
1097
0
  }
1098
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1099
0
  if( libcthreads_read_write_lock_grab_for_read(
1100
0
       internal_partition->read_write_lock,
1101
0
       error ) != 1 )
1102
0
  {
1103
0
    libcerror_error_set(
1104
0
     error,
1105
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1106
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1107
0
     "%s: unable to grab read/write lock for reading.",
1108
0
     function );
1109
1110
0
    return( -1 );
1111
0
  }
1112
0
#endif
1113
0
  *offset = internal_partition->current_offset;
1114
1115
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1116
0
  if( libcthreads_read_write_lock_release_for_read(
1117
0
       internal_partition->read_write_lock,
1118
0
       error ) != 1 )
1119
0
  {
1120
0
    libcerror_error_set(
1121
0
     error,
1122
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1123
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1124
0
     "%s: unable to release read/write lock for reading.",
1125
0
     function );
1126
1127
0
    return( -1 );
1128
0
  }
1129
0
#endif
1130
0
  return( 1 );
1131
0
}
1132
1133
/* Retrieves the partition size
1134
 * Returns 1 if successful or -1 on error
1135
 */
1136
int libvsapm_partition_get_size(
1137
     libvsapm_partition_t *partition,
1138
     size64_t *size,
1139
     libcerror_error_t **error )
1140
0
{
1141
0
  libvsapm_internal_partition_t *internal_partition = NULL;
1142
0
  static char *function                             = "libvsapm_partition_get_size";
1143
1144
0
  if( partition == NULL )
1145
0
  {
1146
0
    libcerror_error_set(
1147
0
     error,
1148
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1149
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1150
0
     "%s: invalid partition.",
1151
0
     function );
1152
1153
0
    return( -1 );
1154
0
  }
1155
0
  internal_partition = (libvsapm_internal_partition_t *) partition;
1156
1157
0
  if( size == NULL )
1158
0
  {
1159
0
    libcerror_error_set(
1160
0
     error,
1161
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1162
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1163
0
     "%s: invalid size.",
1164
0
     function );
1165
1166
0
    return( -1 );
1167
0
  }
1168
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1169
0
  if( libcthreads_read_write_lock_grab_for_read(
1170
0
       internal_partition->read_write_lock,
1171
0
       error ) != 1 )
1172
0
  {
1173
0
    libcerror_error_set(
1174
0
     error,
1175
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1176
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1177
0
     "%s: unable to grab read/write lock for reading.",
1178
0
     function );
1179
1180
0
    return( -1 );
1181
0
  }
1182
0
#endif
1183
0
  *size = internal_partition->size;
1184
1185
0
#if defined( HAVE_MULTI_THREAD_SUPPORT )
1186
0
  if( libcthreads_read_write_lock_release_for_read(
1187
0
       internal_partition->read_write_lock,
1188
0
       error ) != 1 )
1189
0
  {
1190
0
    libcerror_error_set(
1191
0
     error,
1192
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1193
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1194
0
     "%s: unable to release read/write lock for reading.",
1195
0
     function );
1196
1197
0
    return( -1 );
1198
0
  }
1199
0
#endif
1200
0
  return( 1 );
1201
0
}
1202