Coverage Report

Created: 2023-06-07 06:53

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