Coverage Report

Created: 2024-10-02 06:58

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