Coverage Report

Created: 2024-02-25 07:19

/src/libcreg/libfdata/libfdata_area.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The area functions
3
 *
4
 * Copyright (C) 2010-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 "libfdata_area.h"
27
#include "libfdata_definitions.h"
28
#include "libfdata_libcdata.h"
29
#include "libfdata_libcerror.h"
30
#include "libfdata_libcnotify.h"
31
#include "libfdata_libfcache.h"
32
#include "libfdata_mapped_range.h"
33
#include "libfdata_range.h"
34
#include "libfdata_segments_array.h"
35
#include "libfdata_types.h"
36
#include "libfdata_unused.h"
37
38
/* Creates an area
39
 * Make sure the value area is referencing, is set to NULL
40
 *
41
 * If the flag LIBFDATA_DATA_HANDLE_FLAG_MANAGED is set the area
42
 * takes over management of the data handle and the data handle is freed when
43
 * no longer needed
44
 *
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libfdata_area_initialize(
48
     libfdata_area_t **area,
49
     size64_t element_data_size,
50
     intptr_t *data_handle,
51
     int (*free_data_handle)(
52
            intptr_t **data_handle,
53
            libcerror_error_t **error ),
54
     int (*clone_data_handle)(
55
            intptr_t **destination_data_handle,
56
            intptr_t *source_data_handle,
57
            libcerror_error_t **error ),
58
     int (*read_element_data)(
59
            intptr_t *data_handle,
60
            intptr_t *file_io_handle,
61
            libfdata_area_t *area,
62
            libfdata_cache_t *cache,
63
            off64_t element_value_offset,
64
            int element_data_file_index,
65
            off64_t element_data_offset,
66
            size64_t element_data_size,
67
            uint32_t element_data_flags,
68
            uint8_t read_flags,
69
            libcerror_error_t **error ),
70
     int (*write_element_data)(
71
            intptr_t *data_handle,
72
            intptr_t *file_io_handle,
73
            libfdata_area_t *area,
74
            libfdata_cache_t *cache,
75
            off64_t element_value_offset,
76
            int element_data_file_index,
77
            off64_t element_data_offset,
78
            size64_t element_data_size,
79
            uint32_t element_data_flags,
80
            uint8_t write_flags,
81
            libcerror_error_t **error ),
82
     uint8_t flags,
83
     libcerror_error_t **error )
84
1.08k
{
85
1.08k
  libfdata_internal_area_t *internal_area = NULL;
86
1.08k
  static char *function                   = "libfdata_area_initialize";
87
88
1.08k
  if( area == NULL )
89
0
  {
90
0
    libcerror_error_set(
91
0
     error,
92
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
93
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
94
0
     "%s: invalid area.",
95
0
     function );
96
97
0
    return( -1 );
98
0
  }
99
1.08k
  if( *area != NULL )
100
0
  {
101
0
    libcerror_error_set(
102
0
     error,
103
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
104
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
105
0
     "%s: invalid area value already set.",
106
0
     function );
107
108
0
    return( -1 );
109
0
  }
110
1.08k
  if( element_data_size == 0 )
111
0
  {
112
0
    libcerror_error_set(
113
0
     error,
114
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
115
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
116
0
     "%s: invalid element data size value zero or less.",
117
0
     function );
118
119
0
    return( -1 );
120
0
  }
121
1.08k
  internal_area = memory_allocate_structure(
122
1.08k
                   libfdata_internal_area_t );
123
124
1.08k
  if( internal_area == NULL )
125
0
  {
126
0
    libcerror_error_set(
127
0
     error,
128
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
129
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
130
0
     "%s: unable to create area.",
131
0
     function );
132
133
0
    goto on_error;
134
0
  }
135
1.08k
  if( memory_set(
136
1.08k
       internal_area,
137
1.08k
       0,
138
1.08k
       sizeof( libfdata_internal_area_t ) ) == NULL )
139
0
  {
140
0
    libcerror_error_set(
141
0
     error,
142
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
143
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
144
0
     "%s: unable to clear area.",
145
0
     function );
146
147
0
    memory_free(
148
0
     internal_area );
149
150
0
    return( -1 );
151
0
  }
152
1.08k
  if( libcdata_array_initialize(
153
1.08k
       &( internal_area->segments_array ),
154
1.08k
       0,
155
1.08k
       error ) != 1 )
156
0
  {
157
0
    libcerror_error_set(
158
0
     error,
159
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
160
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
161
0
     "%s: unable to create segments array.",
162
0
     function );
163
164
0
    goto on_error;
165
0
  }
166
1.08k
  if( libcdata_array_initialize(
167
1.08k
       &( internal_area->mapped_ranges_array ),
168
1.08k
       0,
169
1.08k
       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 mapped ranges array.",
176
0
     function );
177
178
0
    goto on_error;
179
0
  }
180
1.08k
  if( libfcache_date_time_get_timestamp(
181
1.08k
       &( internal_area->timestamp ),
182
1.08k
       error ) != 1 )
183
0
  {
184
0
    libcerror_error_set(
185
0
     error,
186
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
187
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
188
0
     "%s: unable to retrieve cache timestamp.",
189
0
     function );
190
191
0
    goto on_error;
192
0
  }
193
1.08k
  internal_area->element_data_size  = element_data_size;
194
1.08k
  internal_area->flags             |= flags;
195
1.08k
  internal_area->data_handle        = data_handle;
196
1.08k
  internal_area->free_data_handle   = free_data_handle;
197
1.08k
  internal_area->clone_data_handle  = clone_data_handle;
198
1.08k
  internal_area->read_element_data  = read_element_data;
199
1.08k
  internal_area->write_element_data = write_element_data;
200
201
1.08k
  *area = (libfdata_area_t *) internal_area;
202
203
1.08k
  return( 1 );
204
205
0
on_error:
206
0
  if( internal_area != NULL )
207
0
  {
208
0
    if( internal_area->segments_array != NULL )
209
0
    {
210
0
      libcdata_array_free(
211
0
       &( internal_area->segments_array ),
212
0
       NULL,
213
0
       NULL );
214
0
    }
215
0
    memory_free(
216
0
     internal_area );
217
0
  }
218
0
  return( -1 );
219
1.08k
}
220
221
/* Frees an area
222
 * Returns 1 if successful or -1 on error
223
 */
224
int libfdata_area_free(
225
     libfdata_area_t **area,
226
     libcerror_error_t **error )
227
1.08k
{
228
1.08k
  libfdata_internal_area_t *internal_area = NULL;
229
1.08k
  static char *function                   = "libfdata_area_free";
230
1.08k
  int result                              = 1;
231
232
1.08k
  if( area == NULL )
233
0
  {
234
0
    libcerror_error_set(
235
0
     error,
236
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
237
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
238
0
     "%s: invalid area.",
239
0
     function );
240
241
0
    return( -1 );
242
0
  }
243
1.08k
  if( *area != NULL )
244
1.08k
  {
245
1.08k
    internal_area = (libfdata_internal_area_t *) *area;
246
1.08k
    *area         = NULL;
247
248
1.08k
    if( libcdata_array_free(
249
1.08k
         &( internal_area->segments_array ),
250
1.08k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_range_free,
251
1.08k
         error ) != 1 )
252
0
    {
253
0
      libcerror_error_set(
254
0
       error,
255
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
256
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
257
0
       "%s: unable to free segments array.",
258
0
       function );
259
260
0
      result = -1;
261
0
    }
262
1.08k
    if( libcdata_array_free(
263
1.08k
         &( internal_area->mapped_ranges_array ),
264
1.08k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_mapped_range_free,
265
1.08k
         error ) != 1 )
266
0
    {
267
0
      libcerror_error_set(
268
0
       error,
269
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
270
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
271
0
       "%s: unable to free mapped ranges array.",
272
0
       function );
273
274
0
      result = -1;
275
0
    }
276
1.08k
    if( ( internal_area->flags & LIBFDATA_DATA_HANDLE_FLAG_MANAGED ) != 0 )
277
0
    {
278
0
      if( internal_area->data_handle != NULL )
279
0
      {
280
0
        if( internal_area->free_data_handle == NULL )
281
0
        {
282
0
          libcerror_error_set(
283
0
           error,
284
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
285
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
286
0
           "%s: invalid area - missing free data handle function.",
287
0
           function );
288
289
0
          result = -1;
290
0
        }
291
0
        else if( internal_area->free_data_handle(
292
0
                  &( internal_area->data_handle ),
293
0
                  error ) != 1 )
294
0
        {
295
0
          libcerror_error_set(
296
0
           error,
297
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
298
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
299
0
           "%s: unable to free data handle.",
300
0
           function );
301
302
0
          result = -1;
303
0
        }
304
0
      }
305
0
    }
306
1.08k
    memory_free(
307
1.08k
     internal_area );
308
1.08k
  }
309
1.08k
  return( result );
310
1.08k
}
311
312
/* Clones (duplicates) the area
313
 * Returns 1 if successful or -1 on error
314
 */
315
int libfdata_area_clone(
316
     libfdata_area_t **destination_area,
317
     libfdata_area_t *source_area,
318
     libcerror_error_t **error )
319
0
{
320
0
  libfdata_internal_area_t *internal_destination_area = NULL;
321
0
  libfdata_internal_area_t *internal_source_area      = NULL;
322
0
  static char *function                               = "libfdata_area_clone";
323
324
0
  if( destination_area == NULL )
325
0
  {
326
0
    libcerror_error_set(
327
0
     error,
328
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
329
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
330
0
     "%s: invalid destination area.",
331
0
     function );
332
333
0
    return( -1 );
334
0
  }
335
0
  if( *destination_area != NULL )
336
0
  {
337
0
    libcerror_error_set(
338
0
     error,
339
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
340
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
341
0
     "%s: invalid destination area value already set.",
342
0
     function );
343
344
0
    return( -1 );
345
0
  }
346
0
  if( source_area == NULL )
347
0
  {
348
0
    *destination_area = source_area;
349
350
0
    return( 1 );
351
0
  }
352
0
  internal_source_area = (libfdata_internal_area_t *) source_area;
353
354
/* TODO refactor to use libfdata_area_initialize this requires libcdata_array_copy_elements function */
355
0
  internal_destination_area = memory_allocate_structure(
356
0
                               libfdata_internal_area_t );
357
358
0
  if( internal_destination_area == NULL )
359
0
  {
360
0
    libcerror_error_set(
361
0
     error,
362
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
363
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
364
0
     "%s: unable to create destination area.",
365
0
     function );
366
367
0
    goto on_error;
368
0
  }
369
0
  if( memory_set(
370
0
       internal_destination_area,
371
0
       0,
372
0
       sizeof( libfdata_internal_area_t ) ) == NULL )
373
0
  {
374
0
    libcerror_error_set(
375
0
     error,
376
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
377
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
378
0
     "%s: unable to clear destination area.",
379
0
     function );
380
381
0
    memory_free(
382
0
     internal_destination_area );
383
384
0
    return( -1 );
385
0
  }
386
0
  if( internal_source_area->data_handle != NULL )
387
0
  {
388
0
    if( internal_source_area->free_data_handle == NULL )
389
0
    {
390
0
      libcerror_error_set(
391
0
       error,
392
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
393
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
394
0
       "%s: invalid source area - missing free data handle function.",
395
0
       function );
396
397
0
      goto on_error;
398
0
    }
399
0
    if( internal_source_area->clone_data_handle == NULL )
400
0
    {
401
0
      libcerror_error_set(
402
0
       error,
403
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
404
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
405
0
       "%s: invalid source area - missing clone data handle function.",
406
0
       function );
407
408
0
      goto on_error;
409
0
    }
410
0
    if( internal_source_area->clone_data_handle(
411
0
         &( internal_destination_area->data_handle ),
412
0
         internal_source_area->data_handle,
413
0
         error ) != 1 )
414
0
    {
415
0
      libcerror_error_set(
416
0
       error,
417
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
418
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
419
0
       "%s: unable to create destination data handle.",
420
0
       function );
421
422
0
      goto on_error;
423
0
    }
424
0
  }
425
0
  if( libcdata_array_clone(
426
0
       &( internal_destination_area->segments_array ),
427
0
       internal_source_area->segments_array,
428
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_range_free,
429
0
       (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libfdata_range_clone,
430
0
       error ) != 1 )
431
0
  {
432
0
    libcerror_error_set(
433
0
     error,
434
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
435
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
436
0
     "%s: unable to create destination segments array.",
437
0
     function );
438
439
0
    goto on_error;
440
0
  }
441
0
  if( libcdata_array_clone(
442
0
       &( internal_destination_area->mapped_ranges_array ),
443
0
       internal_source_area->mapped_ranges_array,
444
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_mapped_range_free,
445
0
       (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libfdata_mapped_range_clone,
446
0
       error ) != 1 )
447
0
  {
448
0
    libcerror_error_set(
449
0
     error,
450
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
451
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
452
0
     "%s: unable to create destination mapped ranges array.",
453
0
     function );
454
455
0
    goto on_error;
456
0
  }
457
0
  internal_destination_area->element_data_size  = internal_source_area->element_data_size;
458
0
  internal_destination_area->timestamp          = internal_source_area->timestamp;
459
0
  internal_destination_area->flags              = internal_source_area->flags | LIBFDATA_DATA_HANDLE_FLAG_MANAGED;
460
0
  internal_destination_area->data_handle        = internal_source_area->data_handle;
461
0
  internal_destination_area->free_data_handle   = internal_source_area->free_data_handle;
462
0
  internal_destination_area->clone_data_handle  = internal_source_area->clone_data_handle;
463
0
  internal_destination_area->read_element_data  = internal_source_area->read_element_data;
464
0
  internal_destination_area->write_element_data = internal_source_area->write_element_data;
465
466
0
  *destination_area = (libfdata_area_t *) internal_destination_area;
467
468
0
  return( 1 );
469
470
0
on_error:
471
0
  if( internal_destination_area != NULL )
472
0
  {
473
0
    if( internal_destination_area->segments_array != NULL )
474
0
    {
475
0
      libcdata_array_free(
476
0
       &( internal_destination_area->segments_array ),
477
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_range_free,
478
0
       NULL );
479
0
    }
480
0
    if( ( internal_destination_area->data_handle != NULL )
481
0
     && ( internal_source_area->free_data_handle != NULL ) )
482
0
    {
483
0
      internal_source_area->free_data_handle(
484
0
       &( internal_destination_area->data_handle ),
485
0
       NULL );
486
0
    }
487
0
    memory_free(
488
0
     internal_destination_area );
489
0
  }
490
0
  return( -1 );
491
0
}
492
493
/* Segment functions
494
 */
495
496
/* Empties the area
497
 * Returns 1 if successful or -1 on error
498
 */
499
int libfdata_area_empty(
500
     libfdata_area_t *area,
501
     libcerror_error_t **error )
502
0
{
503
0
  libfdata_internal_area_t *internal_area = NULL;
504
0
  static char *function                   = "libfdata_area_empty";
505
506
0
  if( area == NULL )
507
0
  {
508
0
    libcerror_error_set(
509
0
     error,
510
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
511
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
512
0
     "%s: invalid area.",
513
0
     function );
514
515
0
    return( -1 );
516
0
  }
517
0
  internal_area = (libfdata_internal_area_t *) area;
518
519
0
  if( libcdata_array_empty(
520
0
       internal_area->segments_array,
521
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_range_free,
522
0
       error ) != 1 )
523
0
  {
524
0
    libcerror_error_set(
525
0
     error,
526
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
527
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
528
0
     "%s: unable to empty segments array.",
529
0
     function );
530
531
0
    return( -1 );
532
0
  }
533
0
  if( libcdata_array_empty(
534
0
       internal_area->mapped_ranges_array,
535
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_mapped_range_free,
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_FINALIZE_FAILED,
542
0
     "%s: unable to empty mapped ranges array.",
543
0
     function );
544
545
0
    return( -1 );
546
0
  }
547
0
  internal_area->size = 0;
548
549
0
  return( 1 );
550
0
}
551
552
/* Resizes the area
553
 * Returns 1 if successful or -1 on error
554
 */
555
int libfdata_area_resize(
556
     libfdata_area_t *area,
557
     int number_of_segments,
558
     libcerror_error_t **error )
559
0
{
560
0
  libfdata_internal_area_t *internal_area = NULL;
561
0
  static char *function                   = "libfdata_area_resize";
562
563
0
  if( area == NULL )
564
0
  {
565
0
    libcerror_error_set(
566
0
     error,
567
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
568
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
569
0
     "%s: invalid area.",
570
0
     function );
571
572
0
    return( -1 );
573
0
  }
574
0
  internal_area = (libfdata_internal_area_t *) area;
575
576
0
  if( libcdata_array_resize(
577
0
       internal_area->segments_array,
578
0
       number_of_segments,
579
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_range_free,
580
0
       error ) != 1 )
581
0
  {
582
0
    libcerror_error_set(
583
0
     error,
584
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
585
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
586
0
     "%s: unable to resize segments array.",
587
0
     function );
588
589
0
    return( -1 );
590
0
  }
591
0
  if( libcdata_array_resize(
592
0
       internal_area->mapped_ranges_array,
593
0
       number_of_segments,
594
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_mapped_range_free,
595
0
       error ) != 1 )
596
0
  {
597
0
    libcerror_error_set(
598
0
     error,
599
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
600
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
601
0
     "%s: unable to resize mapped ranges array.",
602
0
     function );
603
604
0
    return( -1 );
605
0
  }
606
0
  internal_area->flags |= LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES;
607
608
0
  return( 1 );
609
0
}
610
611
/* Retrieves the number of segments of the area
612
 * Returns 1 if successful or -1 on error
613
 */
614
int libfdata_area_get_number_of_segments(
615
     libfdata_area_t *area,
616
     int *number_of_segments,
617
     libcerror_error_t **error )
618
0
{
619
0
  libfdata_internal_area_t *internal_area = NULL;
620
0
  static char *function                   = "libfdata_area_get_number_of_segments";
621
622
0
  if( area == NULL )
623
0
  {
624
0
    libcerror_error_set(
625
0
     error,
626
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
627
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
628
0
     "%s: invalid area.",
629
0
     function );
630
631
0
    return( -1 );
632
0
  }
633
0
  internal_area = (libfdata_internal_area_t *) area;
634
635
0
  if( libcdata_array_get_number_of_entries(
636
0
       internal_area->segments_array,
637
0
       number_of_segments,
638
0
       error ) != 1 )
639
0
  {
640
0
    libcerror_error_set(
641
0
     error,
642
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
643
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
644
0
     "%s: unable to retrieve number of entries from segments array.",
645
0
     function );
646
647
0
    return( -1 );
648
0
  }
649
0
  return( 1 );
650
0
}
651
652
/* Retrieves the offset and size of a specific segment
653
 * Returns 1 if successful or -1 on error
654
 */
655
int libfdata_area_get_segment_by_index(
656
     libfdata_area_t *area,
657
     int segment_index,
658
     int *segment_file_index,
659
     off64_t *segment_offset,
660
     size64_t *segment_size,
661
     uint32_t *segment_flags,
662
     libcerror_error_t **error )
663
0
{
664
0
  libfdata_internal_area_t *internal_area = NULL;
665
0
  static char *function                   = "libfdata_area_get_segment_by_index";
666
667
0
  if( area == NULL )
668
0
  {
669
0
    libcerror_error_set(
670
0
     error,
671
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
672
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
673
0
     "%s: invalid area.",
674
0
     function );
675
676
0
    return( -1 );
677
0
  }
678
0
  internal_area = (libfdata_internal_area_t *) area;
679
680
0
  if( libfdata_segments_array_get_segment_by_index(
681
0
       internal_area->segments_array,
682
0
       segment_index,
683
0
       segment_file_index,
684
0
       segment_offset,
685
0
       segment_size,
686
0
       segment_flags,
687
0
       error ) != 1 )
688
0
  {
689
0
    libcerror_error_set(
690
0
     error,
691
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
692
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
693
0
     "%s: unable to retrieve segment: %d.",
694
0
     function,
695
0
     segment_index );
696
697
0
    return( -1 );
698
0
  }
699
0
  return( 1 );
700
0
}
701
702
/* Sets the offset and size of a specific segment
703
 * Returns 1 if successful or -1 on error
704
 */
705
int libfdata_area_set_segment_by_index(
706
     libfdata_area_t *area,
707
     int segment_index,
708
     int segment_file_index,
709
     off64_t segment_offset,
710
     size64_t segment_size,
711
     uint32_t segment_flags,
712
     libcerror_error_t **error )
713
0
{
714
0
  libfdata_internal_area_t *internal_area = NULL;
715
0
  static char *function                   = "libfdata_area_set_segment_by_index";
716
717
0
  if( area == NULL )
718
0
  {
719
0
    libcerror_error_set(
720
0
     error,
721
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
722
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
723
0
     "%s: invalid area.",
724
0
     function );
725
726
0
    return( -1 );
727
0
  }
728
0
  internal_area = (libfdata_internal_area_t *) area;
729
730
0
  if( libfdata_segments_array_set_segment_by_index(
731
0
       internal_area->segments_array,
732
0
       internal_area->mapped_ranges_array,
733
0
       &( internal_area->size ),
734
0
       segment_index,
735
0
       segment_file_index,
736
0
       segment_offset,
737
0
       segment_size,
738
0
       segment_flags,
739
0
       error ) != 1 )
740
0
  {
741
0
    libcerror_error_set(
742
0
     error,
743
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
744
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
745
0
     "%s: unable to set segment: %d.",
746
0
     function,
747
0
     segment_index );
748
749
0
    return( -1 );
750
0
  }
751
0
  internal_area->flags |= LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES;
752
753
0
  return( 1 );
754
0
}
755
756
/* Prepends a segment
757
 * Returns 1 if successful or -1 on error
758
 */
759
int libfdata_area_prepend_segment(
760
     libfdata_area_t *area,
761
     int segment_file_index,
762
     off64_t segment_offset,
763
     size64_t segment_size,
764
     uint32_t segment_flags,
765
     libcerror_error_t **error )
766
0
{
767
0
  libfdata_internal_area_t *internal_area = NULL;
768
0
  static char *function                   = "libfdata_area_prepend_segment";
769
770
0
  if( area == NULL )
771
0
  {
772
0
    libcerror_error_set(
773
0
     error,
774
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
775
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
776
0
     "%s: invalid area.",
777
0
     function );
778
779
0
    return( -1 );
780
0
  }
781
0
  internal_area = (libfdata_internal_area_t *) area;
782
783
0
  if( libfdata_segments_array_prepend_segment(
784
0
       internal_area->segments_array,
785
0
       internal_area->mapped_ranges_array,
786
0
       &( internal_area->size ),
787
0
       segment_file_index,
788
0
       segment_offset,
789
0
       segment_size,
790
0
       segment_flags,
791
0
       error ) != 1 )
792
0
  {
793
0
    libcerror_error_set(
794
0
     error,
795
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
796
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
797
0
     "%s: unable to prepend segment.",
798
0
     function );
799
800
0
    return( -1 );
801
0
  }
802
0
  internal_area->flags |= LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES;
803
804
0
  return( 1 );
805
0
}
806
807
/* Appends a segment
808
 * Returns 1 if successful or -1 on error
809
 */
810
int libfdata_area_append_segment(
811
     libfdata_area_t *area,
812
     int *segment_index,
813
     int segment_file_index,
814
     off64_t segment_offset,
815
     size64_t segment_size,
816
     uint32_t segment_flags,
817
     libcerror_error_t **error )
818
1.08k
{
819
1.08k
  libfdata_internal_area_t *internal_area = NULL;
820
1.08k
  static char *function                   = "libfdata_area_append_segment";
821
822
1.08k
  if( area == NULL )
823
0
  {
824
0
    libcerror_error_set(
825
0
     error,
826
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
827
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
828
0
     "%s: invalid area.",
829
0
     function );
830
831
0
    return( -1 );
832
0
  }
833
1.08k
  internal_area = (libfdata_internal_area_t *) area;
834
835
1.08k
  if( libfdata_segments_array_append_segment(
836
1.08k
       internal_area->segments_array,
837
1.08k
       internal_area->mapped_ranges_array,
838
1.08k
       &( internal_area->size ),
839
1.08k
       segment_index,
840
1.08k
       segment_file_index,
841
1.08k
       segment_offset,
842
1.08k
       segment_size,
843
1.08k
       segment_flags,
844
1.08k
       error ) != 1 )
845
0
  {
846
0
    libcerror_error_set(
847
0
     error,
848
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
849
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
850
0
     "%s: unable to append segment.",
851
0
     function );
852
853
0
    return( -1 );
854
0
  }
855
1.08k
  internal_area->flags |= LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES;
856
857
1.08k
  return( 1 );
858
1.08k
}
859
860
/* Area element functions
861
 */
862
863
/* Retrieves the element data size of the area
864
 * Returns 1 if successful or -1 on error
865
 */
866
int libfdata_area_get_element_data_size(
867
     libfdata_area_t *area,
868
     size64_t *element_data_size,
869
     libcerror_error_t **error )
870
0
{
871
0
  libfdata_internal_area_t *internal_area = NULL;
872
0
  static char *function                   = "libfdata_area_get_element_data_size";
873
874
0
  if( area == NULL )
875
0
  {
876
0
    libcerror_error_set(
877
0
     error,
878
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
879
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
880
0
     "%s: invalid area.",
881
0
     function );
882
883
0
    return( -1 );
884
0
  }
885
0
  internal_area = (libfdata_internal_area_t *) area;
886
887
0
  if( element_data_size == NULL )
888
0
  {
889
0
    libcerror_error_set(
890
0
     error,
891
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
892
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
893
0
     "%s: invalid element data size.",
894
0
     function );
895
896
0
    return( -1 );
897
0
  }
898
0
  *element_data_size = internal_area->element_data_size;
899
900
0
  return( 1 );
901
0
}
902
903
/* Area element value functions
904
 */
905
906
/* Retrieves the value an element at a specific offset
907
 * Returns 1 if successful or -1 on error
908
 */
909
int libfdata_area_get_element_value_at_offset(
910
     libfdata_area_t *area,
911
     intptr_t *file_io_handle,
912
     libfdata_cache_t *cache,
913
     off64_t element_value_offset,
914
     intptr_t **element_value,
915
     uint8_t read_flags,
916
     libcerror_error_t **error )
917
11.2k
{
918
11.2k
  libfcache_cache_value_t *cache_value    = NULL;
919
11.2k
  libfdata_internal_area_t *internal_area = NULL;
920
11.2k
  libfdata_range_t *segment_data_range    = NULL;
921
11.2k
  static char *function                   = "libfdata_area_get_element_value_at_offset";
922
11.2k
  off64_t cache_value_offset              = (off64_t) -1;
923
11.2k
  off64_t element_data_offset             = (off64_t) -1;
924
11.2k
  int64_t cache_value_timestamp           = 0;
925
11.2k
  uint32_t element_data_flags             = 0;
926
11.2k
  int cache_entry_index                   = -1;
927
11.2k
  int cache_value_file_index              = -1;
928
11.2k
  int element_data_file_index             = -1;
929
11.2k
  int element_index                       = -1;
930
11.2k
  int number_of_cache_entries             = 0;
931
11.2k
  int result                              = 0;
932
933
11.2k
  if( area == NULL )
934
4
  {
935
4
    libcerror_error_set(
936
4
     error,
937
4
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
938
4
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
939
4
     "%s: invalid area.",
940
4
     function );
941
942
4
    return( -1 );
943
4
  }
944
11.2k
  internal_area = (libfdata_internal_area_t *) area;
945
946
11.2k
  if( internal_area->read_element_data == NULL )
947
0
  {
948
0
    libcerror_error_set(
949
0
     error,
950
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
951
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
952
0
     "%s: invalid area - missing read element data function.",
953
0
     function );
954
955
0
    return( -1 );
956
0
  }
957
11.2k
  if( internal_area->element_data_size == 0 )
958
0
  {
959
0
    libcerror_error_set(
960
0
     error,
961
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
962
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
963
0
     "%s: invalid area - element data size value out of bounds.",
964
0
     function );
965
966
0
    return( -1 );
967
0
  }
968
11.2k
  if( ( internal_area->size == 0 )
969
11.2k
   || ( internal_area->size > (off64_t) INT64_MAX ) )
970
2
  {
971
2
    libcerror_error_set(
972
2
     error,
973
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
974
2
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
975
2
     "%s: invalid area - size value out of bounds.",
976
2
     function );
977
978
2
    return( -1 );
979
2
  }
980
11.2k
  if( ( (size64_t) element_value_offset > internal_area->size )
981
11.2k
   || ( (size64_t) element_value_offset > ( internal_area->size - internal_area->element_data_size ) ) )
982
163
  {
983
163
    libcerror_error_set(
984
163
     error,
985
163
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
986
163
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
987
163
     "%s: invalid element value offset value out of bounds.",
988
163
     function );
989
990
163
    return( -1 );
991
163
  }
992
11.1k
  if( libfdata_segments_array_get_data_range_at_offset(
993
11.1k
       internal_area->segments_array,
994
11.1k
       element_value_offset,
995
11.1k
       &element_data_offset,
996
11.1k
       &segment_data_range,
997
11.1k
       error ) != 1 )
998
0
  {
999
0
    libcerror_error_set(
1000
0
     error,
1001
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1002
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1003
0
     "%s: unable to retrieve segment data range for offset: 0x%08" PRIx64 ".",
1004
0
     function,
1005
0
     element_value_offset );
1006
1007
0
    return( -1 );
1008
0
  }
1009
11.1k
  if( segment_data_range == NULL )
1010
0
  {
1011
0
    libcerror_error_set(
1012
0
     error,
1013
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1014
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1015
0
     "%s: missing segment data range.",
1016
0
     function );
1017
1018
0
    return( -1 );
1019
0
  }
1020
11.1k
  element_data_file_index = segment_data_range->file_index;
1021
11.1k
  element_data_offset    += segment_data_range->offset;
1022
11.1k
  element_data_flags      = segment_data_range->flags;
1023
1024
11.1k
  if( libfcache_cache_get_number_of_entries(
1025
11.1k
       (libfcache_cache_t *) cache,
1026
11.1k
       &number_of_cache_entries,
1027
11.1k
       error ) != 1 )
1028
0
  {
1029
0
    libcerror_error_set(
1030
0
     error,
1031
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1032
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1033
0
     "%s: unable to retrieve number of cache entries.",
1034
0
     function );
1035
1036
0
    return( -1 );
1037
0
  }
1038
11.1k
  if( number_of_cache_entries <= 0 )
1039
0
  {
1040
0
    libcerror_error_set(
1041
0
     error,
1042
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1043
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1044
0
     "%s: invalid number of cache entries value out of bounds.",
1045
0
     function );
1046
1047
0
    return( -1 );
1048
0
  }
1049
11.1k
  element_index = (int) ( element_value_offset / internal_area->element_data_size );
1050
1051
11.1k
  if( ( read_flags & LIBFDATA_READ_FLAG_IGNORE_CACHE ) == 0 )
1052
11.1k
  {
1053
11.1k
    if( internal_area->calculate_cache_entry_index == NULL )
1054
11.1k
    {
1055
11.1k
      cache_entry_index = element_index % number_of_cache_entries;
1056
11.1k
    }
1057
0
    else
1058
0
    {
1059
0
      cache_entry_index = internal_area->calculate_cache_entry_index(
1060
0
                           element_index,
1061
0
                           element_data_file_index,
1062
0
                           element_data_offset,
1063
0
                           internal_area->element_data_size,
1064
0
                           element_data_flags,
1065
0
                           number_of_cache_entries );
1066
0
    }
1067
11.1k
    if( libfcache_cache_get_value_by_index(
1068
11.1k
         (libfcache_cache_t *) cache,
1069
11.1k
         cache_entry_index,
1070
11.1k
         &cache_value,
1071
11.1k
         error ) != 1 )
1072
0
    {
1073
0
      libcerror_error_set(
1074
0
       error,
1075
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1076
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1077
0
       "%s: unable to retrieve cache entry: %d from cache.",
1078
0
       function,
1079
0
       cache_entry_index );
1080
1081
0
      return( -1 );
1082
0
    }
1083
11.1k
    if( cache_value != NULL )
1084
3.58k
    {
1085
3.58k
      if( libfcache_cache_value_get_identifier(
1086
3.58k
           cache_value,
1087
3.58k
           &cache_value_file_index,
1088
3.58k
           &cache_value_offset,
1089
3.58k
           &cache_value_timestamp,
1090
3.58k
           error ) != 1 )
1091
0
      {
1092
0
        libcerror_error_set(
1093
0
         error,
1094
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1095
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1096
0
         "%s: unable to retrieve cache value identifier.",
1097
0
         function );
1098
1099
0
        return( -1 );
1100
0
      }
1101
3.58k
    }
1102
11.1k
    if( ( element_data_file_index == cache_value_file_index )
1103
11.1k
     && ( element_data_offset == cache_value_offset )
1104
11.1k
     && ( internal_area->timestamp == cache_value_timestamp ) )
1105
3.43k
    {
1106
3.43k
      result = 1;
1107
3.43k
    }
1108
#if defined( HAVE_DEBUG_OUTPUT )
1109
    if( libcnotify_verbose != 0 )
1110
    {
1111
      if( result == 0 )
1112
      {
1113
        libcnotify_printf(
1114
         "%s: cache: 0x%08" PRIjx " miss (%d out of %d)\n",
1115
         function,
1116
         (intptr_t) cache,
1117
         cache_entry_index,
1118
         number_of_cache_entries );
1119
      }
1120
      else
1121
      {
1122
        libcnotify_printf(
1123
         "%s: cache: 0x%08" PRIjx " hit (%d out of %d)\n",
1124
         function,
1125
         (intptr_t) cache,
1126
         cache_entry_index,
1127
         number_of_cache_entries );
1128
      }
1129
    }
1130
#endif
1131
11.1k
  }
1132
11.1k
  if( result == 0 )
1133
7.67k
  {
1134
#if defined( HAVE_DEBUG_OUTPUT )
1135
    if( libcnotify_verbose != 0 )
1136
    {
1137
      libcnotify_printf(
1138
       "%s: reading element data at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIu64 "\n",
1139
       function,
1140
       element_data_offset,
1141
       element_data_offset,
1142
       internal_area->element_data_size );
1143
    }
1144
#endif
1145
7.67k
    if( internal_area->read_element_data(
1146
7.67k
         internal_area->data_handle,
1147
7.67k
         file_io_handle,
1148
7.67k
         area,
1149
7.67k
         cache,
1150
7.67k
         element_value_offset,
1151
7.67k
         element_data_file_index,
1152
7.67k
         element_data_offset,
1153
7.67k
         internal_area->element_data_size,
1154
7.67k
         element_data_flags,
1155
7.67k
         read_flags,
1156
7.67k
         error ) != 1 )
1157
197
    {
1158
197
      libcerror_error_set(
1159
197
       error,
1160
197
       LIBCERROR_ERROR_DOMAIN_IO,
1161
197
       LIBCERROR_IO_ERROR_READ_FAILED,
1162
197
       "%s: unable to read element data at offset: 0x%08" PRIx64 ".",
1163
197
       function,
1164
197
       element_data_offset );
1165
1166
197
      return( -1 );
1167
197
    }
1168
7.48k
    if( internal_area->calculate_cache_entry_index == NULL )
1169
7.48k
    {
1170
7.48k
      cache_entry_index = element_index % number_of_cache_entries;
1171
7.48k
    }
1172
0
    else
1173
0
    {
1174
0
      cache_entry_index = internal_area->calculate_cache_entry_index(
1175
0
                           element_index,
1176
0
                           element_data_file_index,
1177
0
                           element_data_offset,
1178
0
                           internal_area->element_data_size,
1179
0
                           element_data_flags,
1180
0
                           number_of_cache_entries );
1181
0
    }
1182
7.48k
    if( libfcache_cache_get_value_by_index(
1183
7.48k
         (libfcache_cache_t *) cache,
1184
7.48k
         cache_entry_index,
1185
7.48k
         &cache_value,
1186
7.48k
         error ) != 1 )
1187
0
    {
1188
0
      libcerror_error_set(
1189
0
       error,
1190
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1191
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1192
0
       "%s: unable to retrieve cache entry: %d from cache.",
1193
0
       function,
1194
0
       cache_entry_index );
1195
1196
0
      return( -1 );
1197
0
    }
1198
7.48k
    if( cache_value != NULL )
1199
7.48k
    {
1200
7.48k
      if( libfcache_cache_value_get_identifier(
1201
7.48k
           cache_value,
1202
7.48k
           &cache_value_file_index,
1203
7.48k
           &cache_value_offset,
1204
7.48k
           &cache_value_timestamp,
1205
7.48k
           error ) != 1 )
1206
0
      {
1207
0
        libcerror_error_set(
1208
0
         error,
1209
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1210
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1211
0
         "%s: unable to retrieve cache value identifier.",
1212
0
         function );
1213
1214
0
        return( -1 );
1215
0
      }
1216
7.48k
    }
1217
7.48k
    if( ( element_data_file_index != cache_value_file_index )
1218
7.48k
     || ( element_data_offset != cache_value_offset )
1219
7.48k
     || ( internal_area->timestamp != cache_value_timestamp ) )
1220
0
    {
1221
0
      libcerror_error_set(
1222
0
       error,
1223
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1224
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1225
0
       "%s: missing cache value.",
1226
0
       function );
1227
1228
0
      return( -1 );
1229
0
    }
1230
7.48k
  }
1231
10.9k
  if( libfcache_cache_value_get_value(
1232
10.9k
       cache_value,
1233
10.9k
       element_value,
1234
10.9k
       error ) != 1 )
1235
0
  {
1236
0
    libcerror_error_set(
1237
0
     error,
1238
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1239
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1240
0
     "%s: unable to retrieve element value.",
1241
0
     function );
1242
1243
0
    return( -1 );
1244
0
  }
1245
10.9k
  return( 1 );
1246
10.9k
}
1247
1248
/* Sets the value of a specific element
1249
 *
1250
 * If the flag LIBFDATA_AREA_ELEMENT_VALUE_FLAG_MANAGED is set the area
1251
 * takes over management of the value and the value is freed when
1252
 * no longer needed.
1253
 *
1254
 * Returns 1 if successful or -1 on error
1255
 */
1256
int libfdata_area_set_element_value_at_offset(
1257
     libfdata_area_t *area,
1258
     intptr_t *file_io_handle LIBFDATA_ATTRIBUTE_UNUSED,
1259
     libfdata_cache_t *cache,
1260
     off64_t element_value_offset,
1261
     intptr_t *element_value,
1262
     int (*free_element_value)(
1263
            intptr_t **element_value,
1264
            libcerror_error_t **error ),
1265
     uint8_t write_flags,
1266
     libcerror_error_t **error )
1267
7.48k
{
1268
7.48k
  libfdata_internal_area_t *internal_area = NULL;
1269
7.48k
  libfdata_range_t *segment_data_range    = NULL;
1270
7.48k
  static char *function                   = "libfdata_area_set_element_value_at_offset";
1271
7.48k
  off64_t element_data_offset             = (off64_t) -1;
1272
7.48k
  uint32_t element_data_flags             = 0;
1273
7.48k
  int cache_entry_index                   = -1;
1274
7.48k
  int element_data_file_index             = -1;
1275
7.48k
  int element_index                       = -1;
1276
7.48k
  int number_of_cache_entries             = 0;
1277
1278
7.48k
  LIBFDATA_UNREFERENCED_PARAMETER( file_io_handle )
1279
1280
7.48k
  if( area == NULL )
1281
0
  {
1282
0
    libcerror_error_set(
1283
0
     error,
1284
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1285
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1286
0
     "%s: invalid area.",
1287
0
     function );
1288
1289
0
    return( -1 );
1290
0
  }
1291
7.48k
  internal_area = (libfdata_internal_area_t *) area;
1292
1293
7.48k
  if( internal_area->element_data_size == 0 )
1294
0
  {
1295
0
    libcerror_error_set(
1296
0
     error,
1297
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1298
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1299
0
     "%s: invalid area - element data size value out of bounds.",
1300
0
     function );
1301
1302
0
    return( -1 );
1303
0
  }
1304
7.48k
  if( ( internal_area->size == 0 )
1305
7.48k
   || ( internal_area->size > (off64_t) INT64_MAX ) )
1306
0
  {
1307
0
    libcerror_error_set(
1308
0
     error,
1309
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1310
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1311
0
     "%s: invalid area - size value out of bounds.",
1312
0
     function );
1313
1314
0
    return( -1 );
1315
0
  }
1316
7.48k
  if( ( (size64_t) element_value_offset > internal_area->size )
1317
7.48k
   || ( (size64_t) element_value_offset > ( internal_area->size - internal_area->element_data_size ) ) )
1318
0
  {
1319
0
    libcerror_error_set(
1320
0
     error,
1321
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1322
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1323
0
     "%s: invalid element value offset value out of bounds.",
1324
0
     function );
1325
1326
0
    return( -1 );
1327
0
  }
1328
7.48k
  if( libfdata_segments_array_get_data_range_at_offset(
1329
7.48k
       internal_area->segments_array,
1330
7.48k
       element_value_offset,
1331
7.48k
       &element_data_offset,
1332
7.48k
       &segment_data_range,
1333
7.48k
       error ) != 1 )
1334
0
  {
1335
0
    libcerror_error_set(
1336
0
     error,
1337
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1338
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1339
0
     "%s: unable to retrieve segment data range for offset: 0x%08" PRIx64 ".",
1340
0
     function,
1341
0
     element_value_offset );
1342
1343
0
    return( -1 );
1344
0
  }
1345
7.48k
  if( segment_data_range == NULL )
1346
0
  {
1347
0
    libcerror_error_set(
1348
0
     error,
1349
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1350
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1351
0
     "%s: missing segment data range.",
1352
0
     function );
1353
1354
0
    return( -1 );
1355
0
  }
1356
7.48k
  element_data_file_index = segment_data_range->file_index;
1357
7.48k
  element_data_offset    += segment_data_range->offset;
1358
7.48k
  element_data_flags      = segment_data_range->flags;
1359
1360
7.48k
  if( libfcache_cache_get_number_of_entries(
1361
7.48k
       (libfcache_cache_t *) cache,
1362
7.48k
       &number_of_cache_entries,
1363
7.48k
       error ) != 1 )
1364
0
  {
1365
0
    libcerror_error_set(
1366
0
     error,
1367
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1368
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1369
0
     "%s: unable to retrieve number of cache entries.",
1370
0
     function );
1371
1372
0
    return( -1 );
1373
0
  }
1374
7.48k
  if( number_of_cache_entries <= 0 )
1375
0
  {
1376
0
    libcerror_error_set(
1377
0
     error,
1378
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1379
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1380
0
     "%s: invalid number of cache entries value out of bounds.",
1381
0
     function );
1382
1383
0
    return( -1 );
1384
0
  }
1385
7.48k
  element_index = (int) ( element_value_offset / internal_area->element_data_size );
1386
1387
7.48k
  if( internal_area->calculate_cache_entry_index == NULL )
1388
7.48k
  {
1389
7.48k
    cache_entry_index = element_index % number_of_cache_entries;
1390
7.48k
  }
1391
0
  else
1392
0
  {
1393
0
    cache_entry_index = internal_area->calculate_cache_entry_index(
1394
0
                         element_index,
1395
0
                         element_data_file_index,
1396
0
                         element_data_offset,
1397
0
                         internal_area->element_data_size,
1398
0
                         element_data_flags,
1399
0
                         number_of_cache_entries );
1400
0
  }
1401
7.48k
  if( libfcache_cache_set_value_by_index(
1402
7.48k
       (libfcache_cache_t *) cache,
1403
7.48k
       cache_entry_index,
1404
7.48k
       element_data_file_index,
1405
7.48k
       element_data_offset,
1406
7.48k
       internal_area->timestamp,
1407
7.48k
       element_value,
1408
7.48k
       free_element_value,
1409
7.48k
       write_flags,
1410
7.48k
       error ) != 1 )
1411
0
  {
1412
0
    libcerror_error_set(
1413
0
     error,
1414
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1415
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1416
0
     "%s: unable to set value in cache entry: %d.",
1417
0
     function,
1418
0
     cache_entry_index );
1419
1420
0
    return( -1 );
1421
0
  }
1422
7.48k
  return( 1 );
1423
7.48k
}
1424
1425
/* Retrieves the size
1426
 * Returns 1 if successful or -1 on error
1427
 */
1428
int libfdata_area_get_size(
1429
     libfdata_area_t *area,
1430
     size64_t *size,
1431
     libcerror_error_t **error )
1432
0
{
1433
0
  libfdata_internal_area_t *internal_area = NULL;
1434
0
  static char *function                   = "libfdata_area_get_size";
1435
1436
0
  if( area == NULL )
1437
0
  {
1438
0
    libcerror_error_set(
1439
0
     error,
1440
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1441
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1442
0
     "%s: invalid area.",
1443
0
     function );
1444
1445
0
    return( -1 );
1446
0
  }
1447
0
  internal_area = (libfdata_internal_area_t *) area;
1448
1449
0
  if( size == NULL )
1450
0
  {
1451
0
    libcerror_error_set(
1452
0
     error,
1453
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1454
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1455
0
     "%s: invalid size.",
1456
0
     function );
1457
1458
0
    return( -1 );
1459
0
  }
1460
0
  if( ( internal_area->flags & LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES ) != 0 )
1461
0
  {
1462
0
    if( libfdata_segments_array_calculate_mapped_ranges(
1463
0
         internal_area->segments_array,
1464
0
         internal_area->mapped_ranges_array,
1465
0
         error ) != 1 )
1466
0
    {
1467
0
      libcerror_error_set(
1468
0
       error,
1469
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1470
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1471
0
       "%s: unable to calculate mapped ranges.",
1472
0
       function );
1473
1474
0
      return( -1 );
1475
0
    }
1476
0
    internal_area->flags &= ~( LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES );
1477
0
  }
1478
0
  *size = internal_area->size;
1479
1480
0
  return( 1 );
1481
0
}
1482