Coverage Report

Created: 2024-02-25 07:19

/src/libfsxfs/libfdata/libfdata_stream.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The stream 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
#if defined( HAVE_UNISTD_H )
27
#include <unistd.h>
28
#endif
29
30
#include "libfdata_definitions.h"
31
#include "libfdata_libcerror.h"
32
#include "libfdata_libcnotify.h"
33
#include "libfdata_mapped_range.h"
34
#include "libfdata_range.h"
35
#include "libfdata_segments_array.h"
36
#include "libfdata_stream.h"
37
#include "libfdata_types.h"
38
#include "libfdata_unused.h"
39
40
/* Creates a stream
41
 * Make sure the value stream is referencing, is set to NULL
42
 *
43
 * If the flag LIBFDATA_DATA_HANDLE_FLAG_MANAGED is set the stream
44
 * takes over management of the data handle and the data handle is freed when
45
 * no longer needed
46
 *
47
 * Returns 1 if successful or -1 on error
48
 */
49
int libfdata_stream_initialize(
50
     libfdata_stream_t **stream,
51
     intptr_t *data_handle,
52
     int (*free_data_handle)(
53
            intptr_t **data_handle,
54
            libcerror_error_t **error ),
55
     int (*clone_data_handle)(
56
            intptr_t **destination_data_handle,
57
            intptr_t *source_data_handle,
58
            libcerror_error_t **error ),
59
     int (*create_segment)(
60
            intptr_t *data_handle,
61
            intptr_t *file_io_handle,
62
            int segment_index,
63
            int *segment_file_index,
64
            off64_t *segment_offset,
65
            size64_t *segment_size,
66
            uint32_t *segment_flags,
67
            libcerror_error_t **error ),
68
     ssize_t (*read_segment_data)(
69
                intptr_t *data_handle,
70
                intptr_t *file_io_handle,
71
                int segment_index,
72
                int segment_file_index,
73
                uint8_t *segment_data,
74
                size_t segment_data_size,
75
                uint32_t segment_flags,
76
                uint8_t read_flags,
77
                libcerror_error_t **error ),
78
     ssize_t (*write_segment_data)(
79
                intptr_t *data_handle,
80
                intptr_t *file_io_handle,
81
                int segment_index,
82
                int segment_file_index,
83
                const uint8_t *segment_data,
84
                size_t segment_data_size,
85
                uint32_t segment_flags,
86
                uint8_t write_flags,
87
                libcerror_error_t **error ),
88
     off64_t (*seek_segment_offset)(
89
                intptr_t *data_handle,
90
                intptr_t *file_io_handle,
91
                int segment_index,
92
                int segment_file_index,
93
                off64_t segment_offset,
94
                libcerror_error_t **error ),
95
     uint8_t flags,
96
     libcerror_error_t **error )
97
0
{
98
0
  libfdata_internal_stream_t *internal_stream = NULL;
99
0
  static char *function                       = "libfdata_stream_initialize";
100
101
0
  if( stream == NULL )
102
0
  {
103
0
    libcerror_error_set(
104
0
     error,
105
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
106
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
107
0
     "%s: invalid stream.",
108
0
     function );
109
110
0
    return( -1 );
111
0
  }
112
0
  if( *stream != NULL )
113
0
  {
114
0
    libcerror_error_set(
115
0
     error,
116
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
117
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
118
0
     "%s: invalid stream value already set.",
119
0
     function );
120
121
0
    return( -1 );
122
0
  }
123
0
  if( ( flags & 0xfe ) != 0 )
124
0
  {
125
0
    libcerror_error_set(
126
0
     error,
127
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
128
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
129
0
     "%s: unsupported flags: 0x%02" PRIx8 ".",
130
0
     function );
131
132
0
    return( -1 );
133
0
  }
134
0
  internal_stream = memory_allocate_structure(
135
0
                     libfdata_internal_stream_t );
136
137
0
  if( internal_stream == NULL )
138
0
  {
139
0
    libcerror_error_set(
140
0
     error,
141
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
142
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
143
0
     "%s: unable to create stream.",
144
0
     function );
145
146
0
    goto on_error;
147
0
  }
148
0
  if( memory_set(
149
0
       internal_stream,
150
0
       0,
151
0
       sizeof( libfdata_internal_stream_t ) ) == NULL )
152
0
  {
153
0
    libcerror_error_set(
154
0
     error,
155
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
156
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
157
0
     "%s: unable to clear stream.",
158
0
     function );
159
160
0
    memory_free(
161
0
     internal_stream );
162
163
0
    return( -1 );
164
0
  }
165
0
  if( libcdata_array_initialize(
166
0
       &( internal_stream->segments_array ),
167
0
       0,
168
0
       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 segments array.",
175
0
     function );
176
177
0
    goto on_error;
178
0
  }
179
0
  if( libcdata_array_initialize(
180
0
       &( internal_stream->mapped_ranges_array ),
181
0
       0,
182
0
       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 create mapped ranges array.",
189
0
     function );
190
191
0
    goto on_error;
192
0
  }
193
0
  internal_stream->segment_offset      = -1;
194
0
  internal_stream->flags              |= flags;
195
0
  internal_stream->data_handle         = data_handle;
196
0
  internal_stream->free_data_handle    = free_data_handle;
197
0
  internal_stream->clone_data_handle   = clone_data_handle;
198
0
  internal_stream->create_segment      = create_segment;
199
0
  internal_stream->read_segment_data   = read_segment_data;
200
0
  internal_stream->write_segment_data  = write_segment_data;
201
0
  internal_stream->seek_segment_offset = seek_segment_offset;
202
203
0
  *stream = (libfdata_stream_t *) internal_stream;
204
205
0
  return( 1 );
206
207
0
on_error:
208
0
  if( internal_stream != NULL )
209
0
  {
210
0
    if( internal_stream->segments_array != NULL )
211
0
    {
212
0
      libcdata_array_free(
213
0
       &( internal_stream->segments_array ),
214
0
       NULL,
215
0
       NULL );
216
0
    }
217
0
    memory_free(
218
0
     internal_stream );
219
0
  }
220
0
  return( -1 );
221
0
}
222
223
/* Frees a stream
224
 * Returns 1 if successful or -1 on error
225
 */
226
int libfdata_stream_free(
227
     libfdata_stream_t **stream,
228
     libcerror_error_t **error )
229
0
{
230
0
  libfdata_internal_stream_t *internal_stream = NULL;
231
0
  static char *function                       = "libfdata_stream_free";
232
0
  int result                                  = 1;
233
234
0
  if( stream == NULL )
235
0
  {
236
0
    libcerror_error_set(
237
0
     error,
238
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
239
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
240
0
     "%s: invalid stream.",
241
0
     function );
242
243
0
    return( -1 );
244
0
  }
245
0
  if( *stream != NULL )
246
0
  {
247
0
    internal_stream = (libfdata_internal_stream_t *) *stream;
248
0
    *stream         = NULL;
249
250
0
    if( libcdata_array_free(
251
0
         &( internal_stream->segments_array ),
252
0
         (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_range_free,
253
0
         error ) != 1 )
254
0
    {
255
0
      libcerror_error_set(
256
0
       error,
257
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
258
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
259
0
       "%s: unable to free the segments array.",
260
0
       function );
261
262
0
      result = -1;
263
0
    }
264
0
    if( libcdata_array_free(
265
0
         &( internal_stream->mapped_ranges_array ),
266
0
         (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_mapped_range_free,
267
0
         error ) != 1 )
268
0
    {
269
0
      libcerror_error_set(
270
0
       error,
271
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
272
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
273
0
       "%s: unable to free the mapped ranges array.",
274
0
       function );
275
276
0
      result = -1;
277
0
    }
278
0
    if( ( internal_stream->flags & LIBFDATA_DATA_HANDLE_FLAG_MANAGED ) != 0 )
279
0
    {
280
0
      if( internal_stream->data_handle != NULL )
281
0
      {
282
0
        if( internal_stream->free_data_handle == NULL )
283
0
        {
284
0
          libcerror_error_set(
285
0
           error,
286
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
287
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
288
0
           "%s: invalid source stream - missing free data handle function.",
289
0
           function );
290
291
0
          result = -1;
292
0
        }
293
0
        else if( internal_stream->free_data_handle(
294
0
                  &( internal_stream->data_handle ),
295
0
                  error ) != 1 )
296
0
        {
297
0
          libcerror_error_set(
298
0
           error,
299
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
300
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
301
0
           "%s: unable to free data handle.",
302
0
           function );
303
304
0
          result = -1;
305
0
        }
306
0
      }
307
0
    }
308
0
    memory_free(
309
0
     internal_stream );
310
0
  }
311
0
  return( result );
312
0
}
313
314
/* Clones (duplicates) the stream
315
 * Returns 1 if successful or -1 on error
316
 */
317
int libfdata_stream_clone(
318
     libfdata_stream_t **destination_stream,
319
     libfdata_stream_t *source_stream,
320
     libcerror_error_t **error )
321
0
{
322
0
  libfdata_internal_stream_t *internal_destination_stream = NULL;
323
0
  libfdata_internal_stream_t *internal_source_stream      = NULL;
324
0
  static char *function                                   = "libfdata_stream_clone";
325
326
0
  if( destination_stream == NULL )
327
0
  {
328
0
    libcerror_error_set(
329
0
     error,
330
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
331
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
332
0
     "%s: invalid destination stream.",
333
0
     function );
334
335
0
    return( -1 );
336
0
  }
337
0
  if( *destination_stream != NULL )
338
0
  {
339
0
    libcerror_error_set(
340
0
     error,
341
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
342
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
343
0
     "%s: destination stream already set.",
344
0
     function );
345
346
0
    return( -1 );
347
0
  }
348
0
  if( source_stream == NULL )
349
0
  {
350
0
    *destination_stream = NULL;
351
352
0
    return( 1 );
353
0
  }
354
0
  internal_source_stream = (libfdata_internal_stream_t *) source_stream;
355
356
0
  internal_destination_stream = memory_allocate_structure(
357
0
                                 libfdata_internal_stream_t );
358
359
0
  if( internal_destination_stream == NULL )
360
0
  {
361
0
    libcerror_error_set(
362
0
     error,
363
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
364
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
365
0
     "%s: unable to create destination stream.",
366
0
     function );
367
368
0
    goto on_error;
369
0
  }
370
0
  if( memory_set(
371
0
       internal_destination_stream,
372
0
       0,
373
0
       sizeof( libfdata_internal_stream_t ) ) == NULL )
374
0
  {
375
0
    libcerror_error_set(
376
0
     error,
377
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
378
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
379
0
     "%s: unable to clear destination stream.",
380
0
     function );
381
382
0
    memory_free(
383
0
     internal_destination_stream );
384
385
0
    return( -1 );
386
0
  }
387
0
  if( internal_source_stream->data_handle != NULL )
388
0
  {
389
0
    if( internal_source_stream->free_data_handle == NULL )
390
0
    {
391
0
      libcerror_error_set(
392
0
       error,
393
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
394
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
395
0
       "%s: invalid source stream - missing free data handle function.",
396
0
       function );
397
398
0
      goto on_error;
399
0
    }
400
0
    if( internal_source_stream->clone_data_handle == NULL )
401
0
    {
402
0
      libcerror_error_set(
403
0
       error,
404
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
405
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
406
0
       "%s: invalid source stream - missing clone data handle function.",
407
0
       function );
408
409
0
      goto on_error;
410
0
    }
411
0
    if( internal_source_stream->clone_data_handle(
412
0
         &( internal_destination_stream->data_handle ),
413
0
         internal_source_stream->data_handle,
414
0
         error ) != 1 )
415
0
    {
416
0
      libcerror_error_set(
417
0
       error,
418
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
419
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
420
0
       "%s: unable to create destination data handle.",
421
0
       function );
422
423
0
      goto on_error;
424
0
    }
425
0
  }
426
0
  if( libcdata_array_clone(
427
0
       &( internal_destination_stream->segments_array ),
428
0
       internal_source_stream->segments_array,
429
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_range_free,
430
0
       (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libfdata_range_clone,
431
0
       error ) != 1 )
432
0
  {
433
0
    libcerror_error_set(
434
0
     error,
435
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
436
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
437
0
     "%s: unable to create destination segments array.",
438
0
     function );
439
440
0
    goto on_error;
441
0
  }
442
0
  if( libcdata_array_clone(
443
0
       &( internal_destination_stream->mapped_ranges_array ),
444
0
       internal_source_stream->mapped_ranges_array,
445
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_mapped_range_free,
446
0
       (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libfdata_mapped_range_clone,
447
0
       error ) != 1 )
448
0
  {
449
0
    libcerror_error_set(
450
0
     error,
451
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
452
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
453
0
     "%s: unable to create destination mapped ranges array.",
454
0
     function );
455
456
0
    goto on_error;
457
0
  }
458
0
  internal_destination_stream->size                = internal_source_stream->size;
459
0
  internal_destination_stream->mapped_size         = internal_source_stream->mapped_size;
460
0
  internal_destination_stream->flags               = internal_source_stream->flags | LIBFDATA_DATA_HANDLE_FLAG_MANAGED;
461
0
  internal_destination_stream->free_data_handle    = internal_source_stream->free_data_handle;
462
0
  internal_destination_stream->clone_data_handle   = internal_source_stream->clone_data_handle;
463
0
  internal_destination_stream->create_segment      = internal_source_stream->create_segment;
464
0
  internal_destination_stream->read_segment_data   = internal_source_stream->read_segment_data;
465
0
  internal_destination_stream->write_segment_data  = internal_source_stream->write_segment_data;
466
0
  internal_destination_stream->seek_segment_offset = internal_source_stream->seek_segment_offset;
467
468
0
  *destination_stream = (libfdata_stream_t *) internal_destination_stream;
469
470
0
  return( 1 );
471
472
0
on_error:
473
0
  if( internal_destination_stream != NULL )
474
0
  {
475
0
    if( internal_destination_stream->segments_array != NULL )
476
0
    {
477
0
      libcdata_array_free(
478
0
       &( internal_destination_stream->segments_array ),
479
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_range_free,
480
0
       NULL );
481
0
    }
482
0
    if( ( internal_destination_stream->data_handle != NULL )
483
0
     && ( internal_source_stream->free_data_handle != NULL ) )
484
0
    {
485
0
      internal_source_stream->free_data_handle(
486
0
       &( internal_destination_stream->data_handle ),
487
0
       NULL );
488
0
    }
489
0
    memory_free(
490
0
     internal_destination_stream );
491
0
  }
492
0
  return( -1 );
493
0
}
494
495
/* Segment functions
496
 */
497
498
/* Empties the stream
499
 * Returns 1 if successful or -1 on error
500
 */
501
int libfdata_stream_empty(
502
     libfdata_stream_t *stream,
503
     libcerror_error_t **error )
504
0
{
505
0
  libfdata_internal_stream_t *internal_stream = NULL;
506
0
  static char *function                       = "libfdata_stream_empty";
507
508
0
  if( stream == NULL )
509
0
  {
510
0
    libcerror_error_set(
511
0
     error,
512
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
513
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
514
0
     "%s: invalid stream.",
515
0
     function );
516
517
0
    return( -1 );
518
0
  }
519
0
  internal_stream = (libfdata_internal_stream_t *) stream;
520
521
0
  if( libcdata_array_empty(
522
0
       internal_stream->segments_array,
523
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_range_free,
524
0
       error ) != 1 )
525
0
  {
526
0
    libcerror_error_set(
527
0
     error,
528
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
529
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
530
0
     "%s: unable to empty segments array.",
531
0
     function );
532
533
0
    return( -1 );
534
0
  }
535
0
  if( libcdata_array_empty(
536
0
       internal_stream->mapped_ranges_array,
537
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_mapped_range_free,
538
0
       error ) != 1 )
539
0
  {
540
0
    libcerror_error_set(
541
0
     error,
542
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
543
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
544
0
     "%s: unable to empty mapped ranges array.",
545
0
     function );
546
547
0
    return( -1 );
548
0
  }
549
0
  internal_stream->size = 0;
550
551
0
  return( 1 );
552
0
}
553
554
/* Resizes the stream
555
 * Returns 1 if successful or -1 on error
556
 */
557
int libfdata_stream_resize(
558
     libfdata_stream_t *stream,
559
     int number_of_segments,
560
     libcerror_error_t **error )
561
0
{
562
0
  libfdata_internal_stream_t *internal_stream = NULL;
563
0
  static char *function                       = "libfdata_stream_resize";
564
565
0
  if( stream == NULL )
566
0
  {
567
0
    libcerror_error_set(
568
0
     error,
569
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
570
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
571
0
     "%s: invalid stream.",
572
0
     function );
573
574
0
    return( -1 );
575
0
  }
576
0
  internal_stream = (libfdata_internal_stream_t *) stream;
577
578
0
  if( libcdata_array_resize(
579
0
       internal_stream->segments_array,
580
0
       number_of_segments,
581
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_range_free,
582
0
       error ) != 1 )
583
0
  {
584
0
    libcerror_error_set(
585
0
     error,
586
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
587
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
588
0
     "%s: unable to resize segments array.",
589
0
     function );
590
591
0
    return( -1 );
592
0
  }
593
0
  if( libcdata_array_resize(
594
0
       internal_stream->mapped_ranges_array,
595
0
       number_of_segments,
596
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_mapped_range_free,
597
0
       error ) != 1 )
598
0
  {
599
0
    libcerror_error_set(
600
0
     error,
601
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
602
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
603
0
     "%s: unable to resize mapped ranges array.",
604
0
     function );
605
606
0
    return( -1 );
607
0
  }
608
0
  internal_stream->flags |= LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES;
609
610
0
  return( 1 );
611
0
}
612
613
/* Reverses the order of the segments
614
 * Returns 1 if successful or -1 on error
615
 */
616
int libfdata_stream_reverse(
617
     libfdata_stream_t *stream,
618
     libcerror_error_t **error )
619
0
{
620
0
  libfdata_internal_stream_t *internal_stream = NULL;
621
0
  static char *function                       = "libfdata_stream_reverse";
622
623
0
  if( stream == NULL )
624
0
  {
625
0
    libcerror_error_set(
626
0
     error,
627
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
628
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
629
0
     "%s: invalid stream.",
630
0
     function );
631
632
0
    return( -1 );
633
0
  }
634
0
  internal_stream = (libfdata_internal_stream_t *) stream;
635
636
0
  if( libcdata_array_reverse(
637
0
       internal_stream->segments_array,
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_SET_FAILED,
644
0
     "%s: unable to reverse segments array.",
645
0
     function );
646
647
0
    return( -1 );
648
0
  }
649
0
  internal_stream->flags |= LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES;
650
651
0
  return( 1 );
652
0
}
653
654
/* Retrieves the number of segments
655
 * Returns 1 if successful or -1 on error
656
 */
657
int libfdata_stream_get_number_of_segments(
658
     libfdata_stream_t *stream,
659
     int *number_of_segments,
660
     libcerror_error_t **error )
661
0
{
662
0
  libfdata_internal_stream_t *internal_stream = NULL;
663
0
  static char *function                       = "libfdata_stream_get_number_of_segments";
664
665
0
  if( stream == NULL )
666
0
  {
667
0
    libcerror_error_set(
668
0
     error,
669
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
670
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
671
0
     "%s: invalid stream.",
672
0
     function );
673
674
0
    return( -1 );
675
0
  }
676
0
  internal_stream = (libfdata_internal_stream_t *) stream;
677
678
0
  if( libcdata_array_get_number_of_entries(
679
0
       internal_stream->segments_array,
680
0
       number_of_segments,
681
0
       error ) != 1 )
682
0
  {
683
0
    libcerror_error_set(
684
0
     error,
685
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
686
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
687
0
     "%s: unable to retrieve number of entries from segments array.",
688
0
     function );
689
690
0
    return( -1 );
691
0
  }
692
0
  return( 1 );
693
0
}
694
695
/* Retrieves a specific segment
696
 * Returns 1 if successful or -1 on error
697
 */
698
int libfdata_stream_get_segment_by_index(
699
     libfdata_stream_t *stream,
700
     int segment_index,
701
     int *segment_file_index,
702
     off64_t *segment_offset,
703
     size64_t *segment_size,
704
     uint32_t *segment_flags,
705
     libcerror_error_t **error )
706
0
{
707
0
  libfdata_internal_stream_t *internal_stream = NULL;
708
0
  static char *function                       = "libfdata_stream_get_segment_by_index";
709
710
0
  if( stream == NULL )
711
0
  {
712
0
    libcerror_error_set(
713
0
     error,
714
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
715
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
716
0
     "%s: invalid stream.",
717
0
     function );
718
719
0
    return( -1 );
720
0
  }
721
0
  internal_stream = (libfdata_internal_stream_t *) stream;
722
723
0
  if( libfdata_segments_array_get_segment_by_index(
724
0
       internal_stream->segments_array,
725
0
       segment_index,
726
0
       segment_file_index,
727
0
       segment_offset,
728
0
       segment_size,
729
0
       segment_flags,
730
0
       error ) != 1 )
731
0
  {
732
0
    libcerror_error_set(
733
0
     error,
734
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
735
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
736
0
     "%s: unable to retrieve segment: %d.",
737
0
     function,
738
0
     segment_index );
739
740
0
    return( -1 );
741
0
  }
742
0
  return( 1 );
743
0
}
744
745
/* Sets a specific segment
746
 * Returns 1 if successful or -1 on error
747
 */
748
int libfdata_stream_set_segment_by_index(
749
     libfdata_stream_t *stream,
750
     int segment_index,
751
     int segment_file_index,
752
     off64_t segment_offset,
753
     size64_t segment_size,
754
     uint32_t segment_flags,
755
     libcerror_error_t **error )
756
0
{
757
0
  libfdata_internal_stream_t *internal_stream = NULL;
758
0
  static char *function                       = "libfdata_stream_set_segment_by_index";
759
760
0
  if( stream == NULL )
761
0
  {
762
0
    libcerror_error_set(
763
0
     error,
764
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
765
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
766
0
     "%s: invalid stream.",
767
0
     function );
768
769
0
    return( -1 );
770
0
  }
771
0
  internal_stream = (libfdata_internal_stream_t *) stream;
772
773
0
  if( libfdata_segments_array_set_segment_by_index(
774
0
       internal_stream->segments_array,
775
0
       internal_stream->mapped_ranges_array,
776
0
       &( internal_stream->size ),
777
0
       segment_index,
778
0
       segment_file_index,
779
0
       segment_offset,
780
0
       segment_size,
781
0
       segment_flags,
782
0
       error ) != 1 )
783
0
  {
784
0
    libcerror_error_set(
785
0
     error,
786
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
787
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
788
0
     "%s: unable to set segment: %d.",
789
0
     function,
790
0
     segment_index );
791
792
0
    return( -1 );
793
0
  }
794
0
  internal_stream->flags |= LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES;
795
796
0
  return( 1 );
797
0
}
798
799
/* Prepends a segment
800
 * Returns 1 if successful or -1 on error
801
 */
802
int libfdata_stream_prepend_segment(
803
     libfdata_stream_t *stream,
804
     int segment_file_index,
805
     off64_t segment_offset,
806
     size64_t segment_size,
807
     uint32_t segment_flags,
808
     libcerror_error_t **error )
809
0
{
810
0
  libfdata_internal_stream_t *internal_stream = NULL;
811
0
  static char *function                       = "libfdata_stream_prepend_segment";
812
813
0
  if( stream == NULL )
814
0
  {
815
0
    libcerror_error_set(
816
0
     error,
817
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
818
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
819
0
     "%s: invalid stream.",
820
0
     function );
821
822
0
    return( -1 );
823
0
  }
824
0
  internal_stream = (libfdata_internal_stream_t *) stream;
825
826
0
  if( libfdata_segments_array_prepend_segment(
827
0
       internal_stream->segments_array,
828
0
       internal_stream->mapped_ranges_array,
829
0
       &( internal_stream->size ),
830
0
       segment_file_index,
831
0
       segment_offset,
832
0
       segment_size,
833
0
       segment_flags,
834
0
       error ) != 1 )
835
0
  {
836
0
    libcerror_error_set(
837
0
     error,
838
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
839
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
840
0
     "%s: unable to prepend segment.",
841
0
     function );
842
843
0
    return( -1 );
844
0
  }
845
0
  internal_stream->flags |= LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES;
846
847
0
  return( 1 );
848
0
}
849
850
/* Appends a segment
851
 * Returns 1 if successful or -1 on error
852
 */
853
int libfdata_stream_append_segment(
854
     libfdata_stream_t *stream,
855
     int *segment_index,
856
     int segment_file_index,
857
     off64_t segment_offset,
858
     size64_t segment_size,
859
     uint32_t segment_flags,
860
     libcerror_error_t **error )
861
0
{
862
0
  libfdata_internal_stream_t *internal_stream = NULL;
863
0
  static char *function                       = "libfdata_stream_append_segment";
864
865
0
  if( stream == NULL )
866
0
  {
867
0
    libcerror_error_set(
868
0
     error,
869
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
870
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
871
0
     "%s: invalid stream.",
872
0
     function );
873
874
0
    return( -1 );
875
0
  }
876
0
  internal_stream = (libfdata_internal_stream_t *) stream;
877
878
0
  if( libfdata_segments_array_append_segment(
879
0
       internal_stream->segments_array,
880
0
       internal_stream->mapped_ranges_array,
881
0
       &( internal_stream->size ),
882
0
       segment_index,
883
0
       segment_file_index,
884
0
       segment_offset,
885
0
       segment_size,
886
0
       segment_flags,
887
0
       error ) != 1 )
888
0
  {
889
0
    libcerror_error_set(
890
0
     error,
891
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
892
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
893
0
     "%s: unable to append segment.",
894
0
     function );
895
896
0
    return( -1 );
897
0
  }
898
0
  return( 1 );
899
0
}
900
901
/* Sets the mapped size
902
 * The mapped size cannot be larger than the stream size
903
 * A value of 0 is equivalent for the stream size
904
 * Returns 1 if successful or -1 on error
905
 */
906
int libfdata_stream_set_mapped_size(
907
     libfdata_stream_t *stream,
908
     size64_t mapped_size,
909
     libcerror_error_t **error )
910
0
{
911
0
  libfdata_internal_stream_t *internal_stream = NULL;
912
0
  static char *function                       = "libfdata_stream_set_mapped_size";
913
914
0
  if( stream == NULL )
915
0
  {
916
0
    libcerror_error_set(
917
0
     error,
918
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
919
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
920
0
     "%s: invalid stream.",
921
0
     function );
922
923
0
    return( -1 );
924
0
  }
925
0
  internal_stream = (libfdata_internal_stream_t *) stream;
926
927
0
  if( mapped_size > internal_stream->size )
928
0
  {
929
0
    libcerror_error_set(
930
0
     error,
931
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
932
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
933
0
     "%s: invalid mapped size value out of bounds.",
934
0
     function );
935
936
0
    return( -1 );
937
0
  }
938
0
  internal_stream->mapped_size = mapped_size;
939
940
0
  return( 1 );
941
0
}
942
943
/* Mapped range functions
944
 */
945
946
/* Retrieves the mapped range of a specific segment
947
 * Returns 1 if successful or -1 on error
948
 */
949
int libfdata_stream_get_segment_mapped_range(
950
     libfdata_stream_t *stream,
951
     int segment_index,
952
     off64_t *mapped_range_offset,
953
     size64_t *mapped_range_size,
954
     libcerror_error_t **error )
955
0
{
956
0
  libfdata_internal_stream_t *internal_stream = NULL;
957
0
  libfdata_mapped_range_t *mapped_range       = NULL;
958
0
  static char *function                       = "libfdata_stream_get_segment_mapped_range";
959
960
0
  if( stream == NULL )
961
0
  {
962
0
    libcerror_error_set(
963
0
     error,
964
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
965
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
966
0
     "%s: invalid stream.",
967
0
     function );
968
969
0
    return( -1 );
970
0
  }
971
0
  internal_stream = (libfdata_internal_stream_t *) stream;
972
973
0
  if( libcdata_array_get_entry_by_index(
974
0
       internal_stream->mapped_ranges_array,
975
0
       segment_index,
976
0
       (intptr_t **) &mapped_range,
977
0
       error ) != 1 )
978
0
  {
979
0
    libcerror_error_set(
980
0
     error,
981
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
982
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
983
0
     "%s: unable to retrieve entry: %d from mapped ranges array.",
984
0
     function,
985
0
     segment_index );
986
987
0
    return( -1 );
988
0
  }
989
0
  if( libfdata_mapped_range_get(
990
0
       mapped_range,
991
0
       mapped_range_offset,
992
0
       mapped_range_size,
993
0
       error ) != 1 )
994
0
  {
995
0
    libcerror_error_set(
996
0
     error,
997
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
998
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
999
0
     "%s: unable to retrieve values from mapped range: %d.",
1000
0
     function,
1001
0
     segment_index );
1002
1003
0
    return( -1 );
1004
0
  }
1005
0
  return( 1 );
1006
0
}
1007
1008
/* Retrieves the segment index for a specific offset
1009
 * The segment_data_offset value is set to the offset relative to the start of the segment
1010
 * Returns 1 if successful, 0 if not or -1 on error
1011
 */
1012
int libfdata_stream_get_segment_index_at_offset(
1013
     libfdata_stream_t *stream,
1014
     off64_t offset,
1015
     int *segment_index,
1016
     off64_t *segment_data_offset,
1017
     libcerror_error_t **error )
1018
0
{
1019
0
  libfdata_internal_stream_t *internal_stream = NULL;
1020
0
  libfdata_mapped_range_t *mapped_range       = NULL;
1021
0
  static char *function                       = "libfdata_stream_get_segment_index_at_offset";
1022
0
  off64_t mapped_range_end_offset             = 0;
1023
0
  off64_t mapped_range_start_offset           = 0;
1024
0
  size64_t mapped_range_size                  = 0;
1025
0
  size64_t stream_size                        = 0;
1026
0
  int initial_segment_index                   = 0;
1027
0
  int number_of_segments                      = 0;
1028
0
  int result                                  = 0;
1029
0
  int search_segment_index                    = 0;
1030
1031
#if defined( HAVE_DEBUG_OUTPUT )
1032
  libfdata_range_t *segment_data_range        = NULL;
1033
  off64_t segment_offset                      = 0;
1034
  size64_t segment_size                       = 0;
1035
  uint32_t segment_flags                      = 0;
1036
  int segment_file_index                      = -1;
1037
#endif
1038
1039
0
  if( stream == NULL )
1040
0
  {
1041
0
    libcerror_error_set(
1042
0
     error,
1043
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1044
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1045
0
     "%s: invalid stream.",
1046
0
     function );
1047
1048
0
    return( -1 );
1049
0
  }
1050
0
  internal_stream = (libfdata_internal_stream_t *) stream;
1051
1052
0
  if( offset < 0 )
1053
0
  {
1054
0
    libcerror_error_set(
1055
0
     error,
1056
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1057
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
1058
0
     "%s: invalid offset value less than zero.",
1059
0
     function );
1060
1061
0
    return( -1 );
1062
0
  }
1063
0
  if( segment_index == NULL )
1064
0
  {
1065
0
    libcerror_error_set(
1066
0
     error,
1067
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1068
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1069
0
     "%s: invalid segment index.",
1070
0
     function );
1071
1072
0
    return( -1 );
1073
0
  }
1074
0
  if( segment_data_offset == NULL )
1075
0
  {
1076
0
    libcerror_error_set(
1077
0
     error,
1078
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1079
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1080
0
     "%s: invalid segment data offset.",
1081
0
     function );
1082
1083
0
    return( -1 );
1084
0
  }
1085
0
  if( ( internal_stream->flags & LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES ) != 0 )
1086
0
  {
1087
0
    if( libfdata_segments_array_calculate_mapped_ranges(
1088
0
         internal_stream->segments_array,
1089
0
         internal_stream->mapped_ranges_array,
1090
0
         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 calculate mapped ranges.",
1097
0
       function );
1098
1099
0
      return( -1 );
1100
0
    }
1101
0
    internal_stream->flags &= ~( LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES );
1102
0
  }
1103
#if defined( HAVE_DEBUG_OUTPUT )
1104
  if( libcnotify_verbose != 0 )
1105
  {
1106
    libcnotify_printf(
1107
     "%s: requested offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
1108
     function,
1109
     offset,
1110
     offset );
1111
  }
1112
#endif
1113
0
  if( internal_stream->mapped_size != 0 )
1114
0
  {
1115
0
    stream_size = internal_stream->mapped_size;
1116
0
  }
1117
0
  else
1118
0
  {
1119
0
    stream_size = internal_stream->size;
1120
0
  }
1121
0
  if( stream_size == 0 )
1122
0
  {
1123
0
    return( 0 );
1124
0
  }
1125
0
  if( libcdata_array_get_number_of_entries(
1126
0
       internal_stream->mapped_ranges_array,
1127
0
       &number_of_segments,
1128
0
       error ) != 1 )
1129
0
  {
1130
0
    libcerror_error_set(
1131
0
     error,
1132
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1133
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1134
0
     "%s: unable to retrieve number of entries from mapped ranges array.",
1135
0
     function );
1136
1137
0
    return( -1 );
1138
0
  }
1139
  /* This assumes a fairly even distribution of the sizes of the segments
1140
   */
1141
0
  initial_segment_index = (int) ( ( number_of_segments * offset ) / stream_size );
1142
1143
  /* Look for the corresponding segment upwards in the array
1144
   */
1145
0
  for( search_segment_index = initial_segment_index;
1146
0
       search_segment_index < number_of_segments;
1147
0
       search_segment_index++ )
1148
0
  {
1149
0
    if( libcdata_array_get_entry_by_index(
1150
0
         internal_stream->mapped_ranges_array,
1151
0
         search_segment_index,
1152
0
         (intptr_t **) &mapped_range,
1153
0
         error ) != 1 )
1154
0
    {
1155
0
      libcerror_error_set(
1156
0
       error,
1157
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1158
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1159
0
       "%s: unable to retrieve entry: %d from mapped ranges array.",
1160
0
       function,
1161
0
       search_segment_index );
1162
1163
0
      return( -1 );
1164
0
    }
1165
0
    if( libfdata_mapped_range_get(
1166
0
         mapped_range,
1167
0
         &mapped_range_start_offset,
1168
0
         &mapped_range_size,
1169
0
         error ) != 1 )
1170
0
    {
1171
0
      libcerror_error_set(
1172
0
       error,
1173
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1174
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1175
0
       "%s: unable to retrieve values from mapped range: %d.",
1176
0
       function,
1177
0
       search_segment_index );
1178
1179
0
      return( -1 );
1180
0
    }
1181
0
    mapped_range_end_offset = mapped_range_start_offset + (off64_t) mapped_range_size;
1182
1183
0
    if( mapped_range_end_offset < mapped_range_start_offset )
1184
0
    {
1185
0
      libcerror_error_set(
1186
0
       error,
1187
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1188
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1189
0
       "%s: invalid segment: %d - mapped range value out of bounds.",
1190
0
       function,
1191
0
       search_segment_index );
1192
1193
0
      return( -1 );
1194
0
    }
1195
#if defined( HAVE_DEBUG_OUTPUT )
1196
    if( libcnotify_verbose != 0 )
1197
    {
1198
      libcnotify_printf(
1199
       "%s: segment: %03d\tmapped range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
1200
       function,
1201
       search_segment_index,
1202
       mapped_range_start_offset,
1203
       mapped_range_end_offset,
1204
       mapped_range_size );
1205
    }
1206
#endif
1207
    /* Check if the offset is in the mapped range
1208
     */
1209
0
    if( ( offset >= mapped_range_start_offset )
1210
0
     && ( offset < mapped_range_end_offset ) )
1211
0
    {
1212
0
      offset -= mapped_range_start_offset;
1213
1214
0
      break;
1215
0
    }
1216
    /* Check if the offset is out of bounds
1217
     */
1218
0
    if( offset < mapped_range_start_offset )
1219
0
    {
1220
0
      search_segment_index = number_of_segments;
1221
1222
0
      break;
1223
0
    }
1224
0
  }
1225
0
  if( search_segment_index >= number_of_segments )
1226
0
  {
1227
    /* Look for the corresponding segment downwards in the array
1228
     */
1229
0
    for( search_segment_index = initial_segment_index;
1230
0
         search_segment_index >= 0;
1231
0
         search_segment_index-- )
1232
0
    {
1233
0
      if( libcdata_array_get_entry_by_index(
1234
0
           internal_stream->mapped_ranges_array,
1235
0
           search_segment_index,
1236
0
           (intptr_t **) &mapped_range,
1237
0
           error ) != 1 )
1238
0
      {
1239
0
        libcerror_error_set(
1240
0
         error,
1241
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1242
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1243
0
         "%s: unable to retrieve entry: %d from mapped ranges array.",
1244
0
         function,
1245
0
         search_segment_index );
1246
1247
0
        return( -1 );
1248
0
      }
1249
0
      if( libfdata_mapped_range_get(
1250
0
           mapped_range,
1251
0
           &mapped_range_start_offset,
1252
0
           &mapped_range_size,
1253
0
           error ) != 1 )
1254
0
      {
1255
0
        libcerror_error_set(
1256
0
         error,
1257
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1258
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1259
0
         "%s: unable to retrieve values from mapped range: %d.",
1260
0
         function,
1261
0
         search_segment_index );
1262
1263
0
        return( -1 );
1264
0
      }
1265
0
      mapped_range_end_offset = mapped_range_start_offset + (off64_t) mapped_range_size;
1266
1267
0
      if( mapped_range_end_offset < mapped_range_start_offset )
1268
0
      {
1269
0
        libcerror_error_set(
1270
0
         error,
1271
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1272
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1273
0
         "%s: invalid segment: %d - mapped range value out of bounds.",
1274
0
         function,
1275
0
         search_segment_index );
1276
1277
0
        return( -1 );
1278
0
      }
1279
#if defined( HAVE_DEBUG_OUTPUT )
1280
      if( libcnotify_verbose != 0 )
1281
      {
1282
        libcnotify_printf(
1283
         "%s: segment: %03d\tmapped range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
1284
         function,
1285
         search_segment_index,
1286
         mapped_range_start_offset,
1287
         mapped_range_end_offset,
1288
         mapped_range_size );
1289
      }
1290
#endif
1291
      /* Check if the offset is in the mapped range
1292
       */
1293
0
      if( ( offset >= mapped_range_start_offset )
1294
0
       && ( offset < mapped_range_end_offset ) )
1295
0
      {
1296
0
        offset -= mapped_range_start_offset;
1297
1298
0
        break;
1299
0
      }
1300
      /* Check if the offset is out of bounds
1301
       */
1302
0
      if( offset > mapped_range_start_offset )
1303
0
      {
1304
0
        search_segment_index--;
1305
1306
0
        break;
1307
0
      }
1308
0
    }
1309
0
  }
1310
0
  if( ( search_segment_index >= 0 )
1311
0
   && ( search_segment_index < number_of_segments ) )
1312
0
  {
1313
0
    if( offset < 0 )
1314
0
    {
1315
0
      libcerror_error_set(
1316
0
       error,
1317
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1318
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1319
0
       "%s: invalid offset value out of bounds.",
1320
0
       function );
1321
1322
0
      return( -1 );
1323
0
    }
1324
0
    *segment_data_offset = offset;
1325
1326
#if defined( HAVE_DEBUG_OUTPUT )
1327
    if( libcnotify_verbose != 0 )
1328
    {
1329
      if( libcdata_array_get_entry_by_index(
1330
           internal_stream->segments_array,
1331
           search_segment_index,
1332
           (intptr_t **) &segment_data_range,
1333
           error ) != 1 )
1334
      {
1335
        libcerror_error_set(
1336
         error,
1337
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1338
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1339
         "%s: unable to retrieve entry: %d from segments array.",
1340
         function,
1341
         search_segment_index );
1342
1343
        return( -1 );
1344
      }
1345
      if( libfdata_range_get(
1346
           segment_data_range,
1347
           &segment_file_index,
1348
           &segment_offset,
1349
           &segment_size,
1350
           &segment_flags,
1351
           error ) != 1 )
1352
      {
1353
        libcerror_error_set(
1354
         error,
1355
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1356
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1357
         "%s: unable to retrieve segment: %d data range values.",
1358
         function,
1359
         search_segment_index );
1360
1361
        return( -1 );
1362
      }
1363
      libcnotify_printf(
1364
       "%s: segment: %03d\tfile index: %03d offset: %" PRIi64 " - %" PRIi64 " (0x%08" PRIx64 " - 0x%08" PRIx64 ") (size: %" PRIu64 ")\n",
1365
       function,
1366
       search_segment_index,
1367
       segment_file_index,
1368
       segment_offset,
1369
       segment_offset + segment_size,
1370
       segment_offset,
1371
       segment_offset + segment_size,
1372
       segment_size );
1373
    }
1374
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1375
1376
0
    result = 1;
1377
0
  }
1378
0
  if( result == 1 )
1379
0
  {
1380
0
    *segment_index = search_segment_index;
1381
0
  }
1382
#if defined( HAVE_DEBUG_OUTPUT )
1383
  if( libcnotify_verbose != 0 )
1384
  {
1385
    libcnotify_printf(
1386
     "\n" );
1387
  }
1388
#endif
1389
0
  return( result );
1390
0
}
1391
1392
/* Retrieves the segment for a specific offset
1393
 * The segment_data_offset value is set to the offset relative to the start of the segment
1394
 * Returns 1 if successful, 0 if not or -1 on error
1395
 */
1396
int libfdata_stream_get_segment_at_offset(
1397
     libfdata_stream_t *stream,
1398
     off64_t offset,
1399
     int *segment_index,
1400
     off64_t *segment_data_offset,
1401
     int *segment_file_index,
1402
     off64_t *segment_offset,
1403
     size64_t *segment_size,
1404
     uint32_t *segment_flags,
1405
     libcerror_error_t **error )
1406
0
{
1407
0
  libfdata_internal_stream_t *internal_stream = NULL;
1408
0
  libfdata_range_t *segment_data_range        = NULL;
1409
0
  static char *function                       = "libfdata_stream_get_segment_at_offset";
1410
0
  int result                                  = 0;
1411
1412
0
  if( stream == NULL )
1413
0
  {
1414
0
    libcerror_error_set(
1415
0
     error,
1416
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1417
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1418
0
     "%s: invalid stream.",
1419
0
     function );
1420
1421
0
    return( -1 );
1422
0
  }
1423
0
  internal_stream = (libfdata_internal_stream_t *) stream;
1424
1425
0
  if( segment_index == NULL )
1426
0
  {
1427
0
    libcerror_error_set(
1428
0
     error,
1429
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1430
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1431
0
     "%s: invalid segment index.",
1432
0
     function );
1433
1434
0
    return( -1 );
1435
0
  }
1436
0
  result = libfdata_stream_get_segment_index_at_offset(
1437
0
            stream,
1438
0
            offset,
1439
0
            segment_index,
1440
0
            segment_data_offset,
1441
0
            error );
1442
1443
0
  if( result == -1 )
1444
0
  {
1445
0
    libcerror_error_set(
1446
0
     error,
1447
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1448
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1449
0
     "%s: unable to retrieve segment index at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1450
0
     function,
1451
0
     offset,
1452
0
     offset );
1453
1454
0
    return( -1 );
1455
0
  }
1456
0
  else if( result != 0 )
1457
0
  {
1458
0
    if( libcdata_array_get_entry_by_index(
1459
0
         internal_stream->segments_array,
1460
0
         *segment_index,
1461
0
         (intptr_t **) &segment_data_range,
1462
0
         error ) != 1 )
1463
0
    {
1464
0
      libcerror_error_set(
1465
0
       error,
1466
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1467
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1468
0
       "%s: unable to retrieve entry: %d from segments array.",
1469
0
       function,
1470
0
       *segment_index );
1471
1472
0
      return( -1 );
1473
0
    }
1474
0
    if( libfdata_range_get(
1475
0
         segment_data_range,
1476
0
         segment_file_index,
1477
0
         segment_offset,
1478
0
         segment_size,
1479
0
         segment_flags,
1480
0
         error ) != 1 )
1481
0
    {
1482
0
      libcerror_error_set(
1483
0
       error,
1484
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1485
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1486
0
       "%s: unable to retrieve segment: %d data range values.",
1487
0
       function,
1488
0
       *segment_index );
1489
1490
0
      return( -1 );
1491
0
    }
1492
0
  }
1493
0
  return( result );
1494
0
}
1495
1496
/* IO functions
1497
 */
1498
1499
/* Reads data from the current offset into a buffer
1500
 * Returns the number of bytes read or -1 on error
1501
 */
1502
ssize_t libfdata_stream_read_buffer(
1503
         libfdata_stream_t *stream,
1504
         intptr_t *file_io_handle,
1505
         uint8_t *buffer,
1506
         size_t buffer_size,
1507
         uint8_t read_flags,
1508
         libcerror_error_t **error )
1509
0
{
1510
0
  libfdata_internal_stream_t *internal_stream = NULL;
1511
0
  static char *function                       = "libfdata_stream_read_buffer";
1512
0
  off64_t result_offset                       = 0;
1513
0
  off64_t segment_offset                      = 0;
1514
0
  size64_t segment_size                       = 0;
1515
0
  size64_t segment_data_size                  = 0;
1516
0
  size64_t stream_size                        = 0;
1517
0
  size_t buffer_offset                        = 0;
1518
0
  size_t read_size                            = 0;
1519
0
  ssize_t read_count                          = 0;
1520
0
  uint32_t segment_flags                      = 0;
1521
0
  int segment_file_index                      = 0;
1522
1523
0
  if( stream == NULL )
1524
0
  {
1525
0
    libcerror_error_set(
1526
0
     error,
1527
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1528
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1529
0
     "%s: invalid stream.",
1530
0
     function );
1531
1532
0
    return( -1 );
1533
0
  }
1534
0
  internal_stream = (libfdata_internal_stream_t *) stream;
1535
1536
0
  if( internal_stream->read_segment_data == NULL )
1537
0
  {
1538
0
    libcerror_error_set(
1539
0
     error,
1540
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1541
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1542
0
     "%s: invalid stream - missing read segment data function.",
1543
0
     function );
1544
1545
0
    return( -1 );
1546
0
  }
1547
0
  if( internal_stream->seek_segment_offset == NULL )
1548
0
  {
1549
0
    libcerror_error_set(
1550
0
     error,
1551
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1552
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1553
0
     "%s: invalid stream - missing seek segment offset function.",
1554
0
     function );
1555
1556
0
    return( -1 );
1557
0
  }
1558
0
  if( buffer == NULL )
1559
0
  {
1560
0
    libcerror_error_set(
1561
0
     error,
1562
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1563
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1564
0
     "%s: invalid buffer.",
1565
0
     function );
1566
1567
0
    return( -1 );
1568
0
  }
1569
0
  if( buffer_size > (size_t) SSIZE_MAX )
1570
0
  {
1571
0
    libcerror_error_set(
1572
0
     error,
1573
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1574
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1575
0
     "%s: invalid buffer size value exceeds maximum.",
1576
0
     function );
1577
1578
0
    return( -1 );
1579
0
  }
1580
0
  if( internal_stream->current_offset < 0 )
1581
0
  {
1582
0
    libcerror_error_set(
1583
0
     error,
1584
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1585
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1586
0
     "%s: invalid stream - current offset value out of bounds.",
1587
0
     function );
1588
1589
0
    return( -1 );
1590
0
  }
1591
0
  if( internal_stream->mapped_size != 0 )
1592
0
  {
1593
0
    stream_size = internal_stream->mapped_size;
1594
0
  }
1595
0
  else
1596
0
  {
1597
0
    stream_size = internal_stream->size;
1598
0
  }
1599
  /* Bail out early for requests to read empty buffers and beyond the end of the stream
1600
   */
1601
0
  if( (size64_t) internal_stream->current_offset >= stream_size )
1602
0
  {
1603
0
    buffer_size = 0;
1604
0
  }
1605
0
  else if( (size64_t) buffer_size > ( stream_size - internal_stream->current_offset ) )
1606
0
  {
1607
0
    buffer_size = (size_t) ( stream_size - internal_stream->current_offset );
1608
0
  }
1609
0
  if( buffer_size == 0 )
1610
0
  {
1611
0
    return( 0 );
1612
0
  }
1613
0
  if( internal_stream->current_segment_data_range == NULL )
1614
0
  {
1615
0
    if( libcdata_array_get_entry_by_index(
1616
0
         internal_stream->segments_array,
1617
0
         internal_stream->current_segment_index,
1618
0
         (intptr_t **) &( internal_stream->current_segment_data_range ),
1619
0
         error ) != 1 )
1620
0
    {
1621
0
      libcerror_error_set(
1622
0
       error,
1623
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1624
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1625
0
       "%s: unable to retrieve entry: %d from segments array.",
1626
0
       function,
1627
0
       internal_stream->current_segment_index );
1628
1629
0
      return( -1 );
1630
0
    }
1631
0
  }
1632
0
  if( libfdata_range_get(
1633
0
       internal_stream->current_segment_data_range,
1634
0
       &segment_file_index,
1635
0
       &segment_offset,
1636
0
       &segment_size,
1637
0
       &segment_flags,
1638
0
       error ) != 1 )
1639
0
  {
1640
0
    libcerror_error_set(
1641
0
     error,
1642
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1643
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1644
0
     "%s: unable to retrieve segment: %d data range values.",
1645
0
     function,
1646
0
     internal_stream->current_segment_index );
1647
1648
0
    return( -1 );
1649
0
  }
1650
0
  if( ( internal_stream->segment_data_offset < 0 )
1651
0
   || ( segment_offset > ( INT64_MAX - internal_stream->segment_data_offset ) )
1652
0
   || ( (size64_t) internal_stream->segment_data_offset >= segment_size ) )
1653
0
  {
1654
0
    libcerror_error_set(
1655
0
     error,
1656
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1657
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1658
0
     "%s: invalid stream - segment data offset value out of bounds.",
1659
0
     function );
1660
1661
0
    return( -1 );
1662
0
  }
1663
0
  segment_offset += internal_stream->segment_data_offset;
1664
1665
0
  segment_data_size = segment_size - internal_stream->segment_data_offset;
1666
1667
  /* Make sure the file IO handle is pointing to the correct offset
1668
   */
1669
0
  result_offset = internal_stream->seek_segment_offset(
1670
0
                   internal_stream->data_handle,
1671
0
                   file_io_handle,
1672
0
                   internal_stream->current_segment_index,
1673
0
                   segment_file_index,
1674
0
                   segment_offset,
1675
0
                   error );
1676
1677
0
  if( result_offset != segment_offset )
1678
0
  {
1679
0
    libcerror_error_set(
1680
0
     error,
1681
0
     LIBCERROR_ERROR_DOMAIN_IO,
1682
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
1683
0
     "%s: unable to seek segment: %d offset: %" PRIi64 " (0x%08" PRIx64 ").",
1684
0
     function,
1685
0
     internal_stream->current_segment_index,
1686
0
     segment_offset,
1687
0
     segment_offset );
1688
1689
0
    return( -1 );
1690
0
  }
1691
0
  internal_stream->segment_offset = segment_offset;
1692
1693
0
  while( buffer_size > 0 )
1694
0
  {
1695
0
    if( (size64_t) buffer_size <= segment_data_size )
1696
0
    {
1697
0
      read_size = buffer_size;
1698
0
    }
1699
0
    else
1700
0
    {
1701
0
      read_size = (size_t) segment_data_size;
1702
0
    }
1703
0
    if( read_size == 0 )
1704
0
    {
1705
0
      break;
1706
0
    }
1707
0
    read_count = internal_stream->read_segment_data(
1708
0
                  internal_stream->data_handle,
1709
0
                  file_io_handle,
1710
0
                  internal_stream->current_segment_index,
1711
0
                  segment_file_index,
1712
0
                  &( buffer[ buffer_offset ]),
1713
0
                  read_size,
1714
0
                  segment_flags,
1715
0
                  read_flags,
1716
0
                  error );
1717
1718
0
    if( read_count != (ssize_t) read_size )
1719
0
    {
1720
0
      libcerror_error_set(
1721
0
       error,
1722
0
       LIBCERROR_ERROR_DOMAIN_IO,
1723
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1724
0
       "%s: unable to read segment: %d data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1725
0
       function,
1726
0
       internal_stream->current_segment_index,
1727
0
       segment_offset,
1728
0
       segment_offset );
1729
1730
0
      return( -1 );
1731
0
    }
1732
0
    internal_stream->current_offset      += read_size;
1733
0
    internal_stream->segment_offset      += read_size;
1734
0
    internal_stream->segment_data_offset += read_size;
1735
0
    segment_offset                       += read_size;
1736
0
    segment_data_size                    -= read_size;
1737
0
    buffer_size                          -= read_size;
1738
0
    buffer_offset                        += read_size;
1739
1740
0
    if( (size64_t) internal_stream->current_offset >= stream_size )
1741
0
    {
1742
0
      break;
1743
0
    }
1744
0
    if( (size64_t) internal_stream->segment_data_offset >= segment_size )
1745
0
    {
1746
0
      if( (size64_t) internal_stream->segment_data_offset > segment_size )
1747
0
      {
1748
0
        libcerror_error_set(
1749
0
         error,
1750
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1751
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1752
0
         "%s: invalid stream - segment data offset value out of bounds.",
1753
0
         function );
1754
1755
0
        return( -1 );
1756
0
      }
1757
0
      internal_stream->current_segment_index++;
1758
0
      internal_stream->current_segment_data_range = NULL;
1759
0
      internal_stream->segment_data_offset        = 0;
1760
1761
0
      if( libcdata_array_get_entry_by_index(
1762
0
           internal_stream->segments_array,
1763
0
           internal_stream->current_segment_index,
1764
0
           (intptr_t **) &( internal_stream->current_segment_data_range ),
1765
0
           error ) != 1 )
1766
0
      {
1767
0
        libcerror_error_set(
1768
0
         error,
1769
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1770
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1771
0
         "%s: unable to retrieve entry: %d from segments array.",
1772
0
         function,
1773
0
         internal_stream->current_segment_index );
1774
1775
0
        return( -1 );
1776
0
      }
1777
0
      if( libfdata_range_get(
1778
0
           internal_stream->current_segment_data_range,
1779
0
           &segment_file_index,
1780
0
           &segment_offset,
1781
0
           &segment_size,
1782
0
           &segment_flags,
1783
0
           error ) != 1 )
1784
0
      {
1785
0
        libcerror_error_set(
1786
0
         error,
1787
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1788
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1789
0
         "%s: unable to retrieve segment: %d data range values.",
1790
0
         function,
1791
0
         internal_stream->current_segment_index );
1792
1793
0
        return( -1 );
1794
0
      }
1795
0
      segment_data_size = segment_size;
1796
1797
0
      result_offset = internal_stream->seek_segment_offset(
1798
0
                       internal_stream->data_handle,
1799
0
                       file_io_handle,
1800
0
                       internal_stream->current_segment_index,
1801
0
                       segment_file_index,
1802
0
                       segment_offset,
1803
0
                       error );
1804
1805
0
      if( result_offset != segment_offset )
1806
0
      {
1807
0
        libcerror_error_set(
1808
0
         error,
1809
0
         LIBCERROR_ERROR_DOMAIN_IO,
1810
0
         LIBCERROR_IO_ERROR_SEEK_FAILED,
1811
0
         "%s: unable to seek segment: %d offset: %" PRIi64 " (0x%08" PRIx64 ").",
1812
0
         function,
1813
0
         internal_stream->current_segment_index,
1814
0
         segment_offset,
1815
0
         segment_offset );
1816
1817
0
        return( -1 );
1818
0
      }
1819
0
      internal_stream->segment_offset = segment_offset;
1820
0
    }
1821
0
  }
1822
0
  return( (ssize_t) buffer_offset );
1823
0
}
1824
1825
/* Reads data at a specific offset into a buffer
1826
 * Returns the number of bytes read or -1 on error
1827
 */
1828
ssize_t libfdata_stream_read_buffer_at_offset(
1829
         libfdata_stream_t *stream,
1830
         intptr_t *file_io_handle,
1831
         uint8_t *buffer,
1832
         size_t buffer_size,
1833
         off64_t offset,
1834
         uint8_t read_flags,
1835
         libcerror_error_t **error )
1836
0
{
1837
0
  static char *function = "libfdata_stream_read_buffer_at_offset";
1838
0
  ssize_t read_count    = 0;
1839
1840
0
  if( libfdata_stream_seek_offset(
1841
0
       stream,
1842
0
       offset,
1843
0
       SEEK_SET,
1844
0
       error ) == -1 )
1845
0
  {
1846
0
    libcerror_error_set(
1847
0
     error,
1848
0
     LIBCERROR_ERROR_DOMAIN_IO,
1849
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
1850
0
     "%s: unable to seek offset.",
1851
0
     function );
1852
1853
0
    return( -1 );
1854
0
  }
1855
0
  read_count = libfdata_stream_read_buffer(
1856
0
                stream,
1857
0
                file_io_handle,
1858
0
                buffer,
1859
0
                buffer_size,
1860
0
                read_flags,
1861
0
                error );
1862
1863
0
  if( read_count < 0 )
1864
0
  {
1865
0
    libcerror_error_set(
1866
0
     error,
1867
0
     LIBCERROR_ERROR_DOMAIN_IO,
1868
0
     LIBCERROR_IO_ERROR_READ_FAILED,
1869
0
     "%s: unable to read buffer.",
1870
0
     function );
1871
1872
0
    return( -1 );
1873
0
  }
1874
0
  return( read_count );
1875
0
}
1876
1877
/* Writes data in the buffer to the current offset
1878
 * Returns the number of bytes written or -1 on error
1879
 */
1880
ssize_t libfdata_stream_write_buffer(
1881
         libfdata_stream_t *stream,
1882
         intptr_t *file_io_handle,
1883
         const uint8_t *buffer,
1884
         size_t buffer_size,
1885
         uint8_t write_flags,
1886
         libcerror_error_t **error )
1887
0
{
1888
0
  libfdata_internal_stream_t *internal_stream = NULL;
1889
0
  static char *function                       = "libfdata_stream_write_buffer";
1890
0
  off64_t result_offset                       = 0;
1891
0
  off64_t segment_offset                      = 0;
1892
0
  size64_t segment_size                       = 0;
1893
0
  size64_t segment_data_size                  = 0;
1894
0
  size_t buffer_offset                        = 0;
1895
0
  size_t write_size                           = 0;
1896
0
  ssize_t write_count                         = 0;
1897
0
  uint32_t segment_flags                      = 0;
1898
0
  int number_of_segments                      = 0;
1899
0
  int result                                  = 0;
1900
0
  int segment_file_index                      = 0;
1901
0
  int segment_index                           = 0;
1902
1903
0
  if( stream == NULL )
1904
0
  {
1905
0
    libcerror_error_set(
1906
0
     error,
1907
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1908
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1909
0
     "%s: invalid stream.",
1910
0
     function );
1911
1912
0
    return( -1 );
1913
0
  }
1914
0
  internal_stream = (libfdata_internal_stream_t *) stream;
1915
1916
0
  if( internal_stream->create_segment == NULL )
1917
0
  {
1918
0
    libcerror_error_set(
1919
0
     error,
1920
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1921
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1922
0
     "%s: invalid stream - missing create segment function.",
1923
0
     function );
1924
1925
0
    return( -1 );
1926
0
  }
1927
0
  if( internal_stream->write_segment_data == NULL )
1928
0
  {
1929
0
    libcerror_error_set(
1930
0
     error,
1931
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1932
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1933
0
     "%s: invalid stream - missing write segment data function.",
1934
0
     function );
1935
1936
0
    return( -1 );
1937
0
  }
1938
0
  if( internal_stream->seek_segment_offset == NULL )
1939
0
  {
1940
0
    libcerror_error_set(
1941
0
     error,
1942
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1943
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1944
0
     "%s: invalid stream - missing seek segment offset function.",
1945
0
     function );
1946
1947
0
    return( -1 );
1948
0
  }
1949
0
  if( buffer == NULL )
1950
0
  {
1951
0
    libcerror_error_set(
1952
0
     error,
1953
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1954
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1955
0
     "%s: invalid buffer.",
1956
0
     function );
1957
1958
0
    return( -1 );
1959
0
  }
1960
0
  if( buffer_size > (size_t) SSIZE_MAX )
1961
0
  {
1962
0
    libcerror_error_set(
1963
0
     error,
1964
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1965
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1966
0
     "%s: invalid buffer size value exceeds maximum.",
1967
0
     function );
1968
1969
0
    return( -1 );
1970
0
  }
1971
0
  if( internal_stream->current_offset < 0 )
1972
0
  {
1973
0
    libcerror_error_set(
1974
0
     error,
1975
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1976
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1977
0
     "%s: invalid stream - current offset value out of bounds.",
1978
0
     function );
1979
1980
0
    return( -1 );
1981
0
  }
1982
  /* Bail out early for requests to write empty buffers
1983
   */
1984
0
  if( buffer_size == 0 )
1985
0
  {
1986
0
    return( 0 );
1987
0
  }
1988
0
  if( libcdata_array_get_number_of_entries(
1989
0
       internal_stream->segments_array,
1990
0
       &number_of_segments,
1991
0
       error ) != 1 )
1992
0
  {
1993
0
    libcerror_error_set(
1994
0
     error,
1995
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1996
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1997
0
     "%s: unable to retrieve number of entries from segments array.",
1998
0
     function );
1999
2000
0
    return( -1 );
2001
0
  }
2002
0
  if( (size64_t) internal_stream->current_offset < internal_stream->size )
2003
0
  {
2004
0
    if( internal_stream->current_segment_data_range == NULL )
2005
0
    {
2006
0
      if( libcdata_array_get_entry_by_index(
2007
0
           internal_stream->segments_array,
2008
0
           internal_stream->current_segment_index,
2009
0
           (intptr_t **) &( internal_stream->current_segment_data_range ),
2010
0
           error ) != 1 )
2011
0
      {
2012
0
        libcerror_error_set(
2013
0
         error,
2014
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2015
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2016
0
         "%s: unable to retrieve entry: %d from segments array.",
2017
0
         function,
2018
0
         internal_stream->current_segment_index );
2019
2020
0
        return( -1 );
2021
0
      }
2022
0
    }
2023
0
    if( libfdata_range_get(
2024
0
         internal_stream->current_segment_data_range,
2025
0
         &segment_file_index,
2026
0
         &segment_offset,
2027
0
         &segment_size,
2028
0
         &segment_flags,
2029
0
         error ) != 1 )
2030
0
    {
2031
0
      libcerror_error_set(
2032
0
       error,
2033
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2034
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2035
0
       "%s: unable to retrieve segment: %d data range values.",
2036
0
       function,
2037
0
       internal_stream->current_segment_index );
2038
2039
0
      return( -1 );
2040
0
    }
2041
0
    if( ( internal_stream->segment_data_offset < 0 )
2042
0
     || ( (size64_t) internal_stream->segment_data_offset >= segment_size ) )
2043
0
    {
2044
0
      libcerror_error_set(
2045
0
       error,
2046
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2047
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2048
0
       "%s: invalid stream - segment data offset value out of bounds.",
2049
0
       function );
2050
2051
0
      return( -1 );
2052
0
    }
2053
0
    segment_offset += internal_stream->segment_data_offset;
2054
2055
0
    segment_data_size = segment_size - internal_stream->segment_data_offset;
2056
0
  }
2057
0
  else while( (size64_t) internal_stream->current_offset >= internal_stream->size )
2058
0
  {
2059
0
    if( internal_stream->current_segment_index < number_of_segments )
2060
0
    {
2061
0
      internal_stream->current_segment_index++;
2062
0
      internal_stream->current_segment_data_range = NULL;
2063
0
    }
2064
0
    internal_stream->segment_data_offset = 0;
2065
2066
0
    result = internal_stream->create_segment(
2067
0
        internal_stream->data_handle,
2068
0
        file_io_handle,
2069
0
        internal_stream->current_segment_index,
2070
0
        &segment_file_index,
2071
0
        &segment_offset,
2072
0
        &segment_size,
2073
0
        &segment_flags,
2074
0
        error );
2075
2076
0
    if( result == -1 )
2077
0
    {
2078
0
      libcerror_error_set(
2079
0
       error,
2080
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2081
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2082
0
       "%s: unable to create segment: %d.",
2083
0
       function,
2084
0
       internal_stream->current_segment_index );
2085
2086
0
      return( -1 );
2087
0
    }
2088
0
    else if( result == 0 )
2089
0
    {
2090
0
      return( 0 );
2091
0
    }
2092
0
    if( libfdata_stream_append_segment(
2093
0
         stream,
2094
0
         &segment_index,
2095
0
         segment_file_index,
2096
0
         segment_offset,
2097
0
         segment_size,
2098
0
         segment_flags,
2099
0
         error ) != 1 )
2100
0
    {
2101
0
      libcerror_error_set(
2102
0
       error,
2103
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2104
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2105
0
       "%s: unable to append segment to stream.",
2106
0
       function );
2107
2108
0
      return( -1 );
2109
0
    }
2110
0
    if( internal_stream->current_segment_index != segment_index )
2111
0
    {
2112
0
      libcerror_error_set(
2113
0
       error,
2114
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2115
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2116
0
       "%s: invalid segment index value out of bounds.",
2117
0
       function );
2118
2119
0
      return( -1 );
2120
0
    }
2121
0
    number_of_segments++;
2122
2123
0
    segment_data_size = segment_size;
2124
0
  }
2125
  /* Make sure the file IO handle is pointing to the correct offset
2126
   */
2127
0
  result_offset = internal_stream->seek_segment_offset(
2128
0
       internal_stream->data_handle,
2129
0
       file_io_handle,
2130
0
       internal_stream->current_segment_index,
2131
0
       segment_file_index,
2132
0
       segment_offset,
2133
0
       error );
2134
2135
0
  if( result_offset != segment_offset )
2136
0
  {
2137
0
    libcerror_error_set(
2138
0
     error,
2139
0
     LIBCERROR_ERROR_DOMAIN_IO,
2140
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
2141
0
     "%s: unable to seek segment: %d offset: %" PRIi64 " (0x%08" PRIx64 ").",
2142
0
     function,
2143
0
     internal_stream->current_segment_index,
2144
0
     segment_offset,
2145
0
     segment_offset );
2146
2147
0
    return( -1 );
2148
0
  }
2149
0
  internal_stream->segment_offset = segment_offset;
2150
2151
0
  while( buffer_size > 0 )
2152
0
  {
2153
0
    if( (size64_t) buffer_size <= segment_data_size )
2154
0
    {
2155
0
      write_size = buffer_size;
2156
0
    }
2157
0
    else
2158
0
    {
2159
0
      write_size = (size_t) segment_data_size;
2160
0
    }
2161
0
    if( write_size == 0 )
2162
0
    {
2163
0
      break;
2164
0
    }
2165
0
    write_count = internal_stream->write_segment_data(
2166
0
                   internal_stream->data_handle,
2167
0
                   file_io_handle,
2168
0
                   internal_stream->current_segment_index,
2169
0
                   segment_file_index,
2170
0
                   &( buffer[ buffer_offset ] ),
2171
0
                   write_size,
2172
0
                   segment_flags,
2173
0
                   write_flags,
2174
0
                   error );
2175
2176
0
    if( write_count != (ssize_t) write_size )
2177
0
    {
2178
0
      libcerror_error_set(
2179
0
       error,
2180
0
       LIBCERROR_ERROR_DOMAIN_IO,
2181
0
       LIBCERROR_IO_ERROR_WRITE_FAILED,
2182
0
       "%s: unable to write segment: %d data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2183
0
       function,
2184
0
       internal_stream->current_segment_index,
2185
0
       segment_offset + internal_stream->segment_data_offset,
2186
0
       segment_offset + internal_stream->segment_data_offset );
2187
2188
0
      return( -1 );
2189
0
    }
2190
0
    internal_stream->current_offset      += write_size;
2191
0
    internal_stream->segment_offset      += write_size;
2192
0
    internal_stream->segment_data_offset += write_size;
2193
0
    segment_offset                       += write_size;
2194
0
    segment_data_size                    -= write_size;
2195
0
    buffer_size                          -= write_size;
2196
0
    buffer_offset                        += write_size;
2197
2198
0
    if( (size64_t) internal_stream->segment_data_offset >= segment_size )
2199
0
    {
2200
0
      if( (size64_t) internal_stream->segment_data_offset > segment_size )
2201
0
      {
2202
0
        libcerror_error_set(
2203
0
         error,
2204
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2205
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2206
0
         "%s: invalid stream - segment data offset value out of bounds.",
2207
0
         function );
2208
2209
0
        return( -1 );
2210
0
      }
2211
0
      internal_stream->current_segment_index++;
2212
0
      internal_stream->current_segment_data_range = NULL;
2213
0
      internal_stream->segment_data_offset        = 0;
2214
2215
0
      if( internal_stream->current_segment_index < number_of_segments )
2216
0
      {
2217
0
        if( libcdata_array_get_entry_by_index(
2218
0
             internal_stream->segments_array,
2219
0
             internal_stream->current_segment_index,
2220
0
             (intptr_t **) &( internal_stream->current_segment_data_range ),
2221
0
             error ) != 1 )
2222
0
        {
2223
0
          libcerror_error_set(
2224
0
           error,
2225
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2226
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2227
0
           "%s: unable to retrieve entry: %d from segments array.",
2228
0
           function,
2229
0
           internal_stream->current_segment_index );
2230
2231
0
          return( -1 );
2232
0
        }
2233
0
        if( libfdata_range_get(
2234
0
             internal_stream->current_segment_data_range,
2235
0
             &segment_file_index,
2236
0
             &segment_offset,
2237
0
             &segment_size,
2238
0
             &segment_flags,
2239
0
             error ) != 1 )
2240
0
        {
2241
0
          libcerror_error_set(
2242
0
           error,
2243
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2244
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2245
0
           "%s: unable to retrieve segment: %d data range values.",
2246
0
           function,
2247
0
           internal_stream->current_segment_index );
2248
2249
0
          return( -1 );
2250
0
        }
2251
0
      }
2252
0
      else
2253
0
      {
2254
0
        result = internal_stream->create_segment(
2255
0
            internal_stream->data_handle,
2256
0
            file_io_handle,
2257
0
            internal_stream->current_segment_index,
2258
0
            &segment_file_index,
2259
0
            &segment_offset,
2260
0
            &segment_size,
2261
0
            &segment_flags,
2262
0
            error );
2263
2264
0
        if( result == -1 )
2265
0
        {
2266
0
          libcerror_error_set(
2267
0
           error,
2268
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2269
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2270
0
           "%s: unable to create segment: %d.",
2271
0
           function,
2272
0
           internal_stream->current_segment_index );
2273
2274
0
          return( -1 );
2275
0
        }
2276
0
        else if( result == 0 )
2277
0
        {
2278
0
          break;
2279
0
        }
2280
0
        if( libfdata_stream_append_segment(
2281
0
             stream,
2282
0
             &segment_index,
2283
0
             segment_file_index,
2284
0
             segment_offset,
2285
0
             segment_size,
2286
0
             segment_flags,
2287
0
             error ) != 1 )
2288
0
        {
2289
0
          libcerror_error_set(
2290
0
           error,
2291
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2292
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2293
0
           "%s: unable to append segment to stream.",
2294
0
           function );
2295
2296
0
          return( -1 );
2297
0
        }
2298
0
        if( internal_stream->current_segment_index != segment_index )
2299
0
        {
2300
0
          libcerror_error_set(
2301
0
           error,
2302
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2303
0
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2304
0
           "%s: invalid segment index value out of bounds.",
2305
0
           function );
2306
2307
0
          return( -1 );
2308
0
        }
2309
0
        number_of_segments++;
2310
0
      }
2311
0
      segment_data_size = segment_size;
2312
2313
0
      result_offset = internal_stream->seek_segment_offset(
2314
0
           internal_stream->data_handle,
2315
0
           file_io_handle,
2316
0
           internal_stream->current_segment_index,
2317
0
           segment_file_index,
2318
0
           segment_offset,
2319
0
           error );
2320
2321
0
      if( result_offset != segment_offset )
2322
0
      {
2323
0
        libcerror_error_set(
2324
0
         error,
2325
0
         LIBCERROR_ERROR_DOMAIN_IO,
2326
0
         LIBCERROR_IO_ERROR_SEEK_FAILED,
2327
0
         "%s: unable to seek segment: %d offset: %" PRIi64 " (0x%08" PRIx64 ").",
2328
0
         function,
2329
0
         internal_stream->current_segment_index,
2330
0
         segment_offset,
2331
0
         segment_offset );
2332
2333
0
        return( -1 );
2334
0
      }
2335
0
      internal_stream->segment_offset = segment_offset;
2336
0
    }
2337
0
  }
2338
0
  return( (ssize_t) buffer_offset );
2339
0
}
2340
2341
/* Seeks a certain offset of the data
2342
 * Returns the offset if seek is successful or -1 on error
2343
 */
2344
off64_t libfdata_stream_seek_offset(
2345
         libfdata_stream_t *stream,
2346
         off64_t offset,
2347
         int whence,
2348
         libcerror_error_t **error )
2349
0
{
2350
0
  libfdata_internal_stream_t *internal_stream = NULL;
2351
0
  static char *function                       = "libfdata_stream_seek_offset";
2352
0
  off64_t segment_data_offset                 = 0;
2353
0
  size64_t stream_size                        = 0;
2354
0
  int segment_index                           = 0;
2355
2356
0
  if( stream == NULL )
2357
0
  {
2358
0
    libcerror_error_set(
2359
0
     error,
2360
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2361
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2362
0
     "%s: invalid stream.",
2363
0
     function );
2364
2365
0
    return( -1 );
2366
0
  }
2367
0
  internal_stream = (libfdata_internal_stream_t *) stream;
2368
2369
0
  if( internal_stream->current_offset < 0 )
2370
0
  {
2371
0
    libcerror_error_set(
2372
0
     error,
2373
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2374
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2375
0
     "%s: invalid stream - current offset value out of bounds.",
2376
0
     function );
2377
2378
0
    return( -1 );
2379
0
  }
2380
0
  if( ( whence != SEEK_CUR )
2381
0
   && ( whence != SEEK_END )
2382
0
   && ( whence != SEEK_SET ) )
2383
0
  {
2384
0
    libcerror_error_set(
2385
0
     error,
2386
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2387
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2388
0
     "%s: unsupported whence.",
2389
0
     function );
2390
2391
0
    return( -1 );
2392
0
  }
2393
0
  if( internal_stream->mapped_size != 0 )
2394
0
  {
2395
0
    stream_size = internal_stream->mapped_size;
2396
0
  }
2397
0
  else
2398
0
  {
2399
0
    stream_size = internal_stream->size;
2400
0
  }
2401
0
  if( whence == SEEK_CUR )
2402
0
  {
2403
0
    offset += internal_stream->current_offset;
2404
0
  }
2405
0
  else if( whence == SEEK_END )
2406
0
  {
2407
0
    offset += (off64_t) stream_size;
2408
0
  }
2409
#if defined( HAVE_VERBOSE_OUTPUT )
2410
  if( libcnotify_verbose != 0 )
2411
  {
2412
    libcnotify_printf(
2413
     "%s: seeking offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
2414
     function,
2415
     offset,
2416
     offset );
2417
  }
2418
#endif
2419
0
  if( internal_stream->current_offset != offset )
2420
0
  {
2421
0
    if( offset < 0 )
2422
0
    {
2423
0
      libcerror_error_set(
2424
0
       error,
2425
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2426
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2427
0
       "%s: offset value out of bounds.",
2428
0
       function );
2429
2430
0
      return( -1 );
2431
0
    }
2432
0
    if( offset < (off64_t) stream_size )
2433
0
    {
2434
0
      if( libfdata_stream_get_segment_index_at_offset(
2435
0
           stream,
2436
0
           offset,
2437
0
           &segment_index,
2438
0
           &segment_data_offset,
2439
0
           error ) != 1 )
2440
0
      {
2441
0
        libcerror_error_set(
2442
0
         error,
2443
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2444
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2445
0
         "%s: unable to retrieve segment index at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2446
0
         function,
2447
0
         offset,
2448
0
         offset );
2449
2450
0
        return( -1 );
2451
0
      }
2452
0
    }
2453
0
    else
2454
0
    {
2455
0
      if( libcdata_array_get_number_of_entries(
2456
0
           internal_stream->segments_array,
2457
0
           &segment_index,
2458
0
           error ) != 1 )
2459
0
      {
2460
0
        libcerror_error_set(
2461
0
         error,
2462
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2463
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2464
0
         "%s: unable to retrieve number of entries from segments array.",
2465
0
         function );
2466
2467
0
        return( -1 );
2468
0
      }
2469
0
      segment_data_offset = 0;
2470
0
    }
2471
0
    internal_stream->current_segment_index      = segment_index;
2472
0
    internal_stream->current_segment_data_range = NULL;
2473
0
    internal_stream->current_offset             = offset;
2474
0
    internal_stream->segment_data_offset        = segment_data_offset;
2475
0
  }
2476
0
  return( offset );
2477
0
}
2478
2479
/* Retrieves the offset
2480
 * Returns 1 if successful or -1 on error
2481
 */
2482
int libfdata_stream_get_offset(
2483
     libfdata_stream_t *stream,
2484
     off64_t *offset,
2485
     libcerror_error_t **error )
2486
0
{
2487
0
  libfdata_internal_stream_t *internal_stream = NULL;
2488
0
  static char *function                       = "libfdata_stream_get_data_offset";
2489
2490
0
  if( stream == NULL )
2491
0
  {
2492
0
    libcerror_error_set(
2493
0
     error,
2494
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2495
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2496
0
     "%s: invalid stream.",
2497
0
     function );
2498
2499
0
    return( -1 );
2500
0
  }
2501
0
  internal_stream = (libfdata_internal_stream_t *) stream;
2502
2503
0
  if( offset == NULL )
2504
0
  {
2505
0
    libcerror_error_set(
2506
0
     error,
2507
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2508
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2509
0
     "%s: invalid offset.",
2510
0
     function );
2511
2512
0
    return( -1 );
2513
0
  }
2514
0
  *offset = internal_stream->current_offset;
2515
2516
0
  return( 1 );
2517
0
}
2518
2519
/* Retrieves the size
2520
 * Returns 1 if successful or -1 on error
2521
 */
2522
int libfdata_stream_get_size(
2523
     libfdata_stream_t *stream,
2524
     size64_t *size,
2525
     libcerror_error_t **error )
2526
0
{
2527
0
  libfdata_internal_stream_t *internal_stream = NULL;
2528
0
  static char *function                       = "libfdata_stream_get_size";
2529
2530
0
  if( stream == NULL )
2531
0
  {
2532
0
    libcerror_error_set(
2533
0
     error,
2534
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2535
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2536
0
     "%s: invalid stream.",
2537
0
     function );
2538
2539
0
    return( -1 );
2540
0
  }
2541
0
  internal_stream = (libfdata_internal_stream_t *) stream;
2542
2543
0
  if( size == NULL )
2544
0
  {
2545
0
    libcerror_error_set(
2546
0
     error,
2547
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2548
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2549
0
     "%s: invalid size.",
2550
0
     function );
2551
2552
0
    return( -1 );
2553
0
  }
2554
0
  if( ( internal_stream->flags & LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES ) != 0 )
2555
0
  {
2556
0
    if( libfdata_segments_array_calculate_mapped_ranges(
2557
0
         internal_stream->segments_array,
2558
0
         internal_stream->mapped_ranges_array,
2559
0
         error ) != 1 )
2560
0
    {
2561
0
      libcerror_error_set(
2562
0
       error,
2563
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2564
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2565
0
       "%s: unable to calculate mapped ranges.",
2566
0
       function );
2567
2568
0
      return( -1 );
2569
0
    }
2570
0
    internal_stream->flags &= ~( LIBFDATA_FLAG_CALCULATE_MAPPED_RANGES );
2571
0
  }
2572
0
  if( internal_stream->mapped_size != 0 )
2573
0
  {
2574
0
    *size = internal_stream->mapped_size;
2575
0
  }
2576
0
  else
2577
0
  {
2578
0
    *size = internal_stream->size;
2579
0
  }
2580
0
  return( 1 );
2581
0
}
2582