Coverage Report

Created: 2025-08-28 07:10

/src/libmdmp/libmdmp/libmdmp_stream.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Section functions
3
 *
4
 * Copyright (C) 2014-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 "libmdmp_definitions.h"
27
#include "libmdmp_io_handle.h"
28
#include "libmdmp_libbfio.h"
29
#include "libmdmp_libcerror.h"
30
#include "libmdmp_libfdata.h"
31
#include "libmdmp_libuna.h"
32
#include "libmdmp_stream.h"
33
#include "libmdmp_stream_io_handle.h"
34
35
/* Creates a stream
36
 * Make sure the value stream is referencing, is set to NULL
37
 * Returns 1 if successful or -1 on error
38
 */
39
int libmdmp_stream_initialize(
40
     libmdmp_stream_t **stream,
41
     libmdmp_io_handle_t *io_handle,
42
     libbfio_handle_t *file_io_handle,
43
     libmdmp_stream_descriptor_t *stream_descriptor,
44
     libcerror_error_t **error )
45
0
{
46
0
  libmdmp_internal_stream_t *internal_stream = NULL;
47
0
  static char *function                      = "libmdmp_stream_initialize";
48
49
0
  if( stream == NULL )
50
0
  {
51
0
    libcerror_error_set(
52
0
     error,
53
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
54
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
55
0
     "%s: invalid stream.",
56
0
     function );
57
58
0
    return( -1 );
59
0
  }
60
0
  if( *stream != NULL )
61
0
  {
62
0
    libcerror_error_set(
63
0
     error,
64
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
65
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
66
0
     "%s: invalid stream value already set.",
67
0
     function );
68
69
0
    return( -1 );
70
0
  }
71
0
  if( stream_descriptor == NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
76
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
77
0
     "%s: invalid stream descriptor.",
78
0
     function );
79
80
0
    return( -1 );
81
0
  }
82
0
  internal_stream = memory_allocate_structure(
83
0
                     libmdmp_internal_stream_t );
84
85
0
  if( internal_stream == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
90
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
91
0
     "%s: unable to create internal stream.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
0
  if( memory_set(
97
0
       internal_stream,
98
0
       0,
99
0
       sizeof( libmdmp_internal_stream_t ) ) == NULL )
100
0
  {
101
0
    libcerror_error_set(
102
0
     error,
103
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
104
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
105
0
     "%s: unable to clear internal stream.",
106
0
     function );
107
108
0
    memory_free(
109
0
     internal_stream );
110
111
0
    return( -1 );
112
0
  }
113
0
  internal_stream->file_io_handle    = file_io_handle;
114
0
  internal_stream->io_handle         = io_handle;
115
0
  internal_stream->stream_descriptor = stream_descriptor;
116
117
0
  *stream = (libmdmp_stream_t *) internal_stream;
118
119
0
  return( 1 );
120
121
0
on_error:
122
0
  if( internal_stream != NULL )
123
0
  {
124
0
    memory_free(
125
0
     internal_stream );
126
0
  }
127
0
  return( -1 );
128
0
}
129
130
/* Frees a stream
131
 * Returns 1 if successful or -1 on error
132
 */
133
int libmdmp_stream_free(
134
     libmdmp_stream_t **stream,
135
     libcerror_error_t **error )
136
0
{
137
0
  libmdmp_internal_stream_t *internal_stream = NULL;
138
0
  static char *function                      = "libmdmp_stream_free";
139
140
0
  if( stream == NULL )
141
0
  {
142
0
    libcerror_error_set(
143
0
     error,
144
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
145
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
146
0
     "%s: invalid stream.",
147
0
     function );
148
149
0
    return( -1 );
150
0
  }
151
0
  if( *stream != NULL )
152
0
  {
153
0
    internal_stream = (libmdmp_internal_stream_t *) *stream;
154
0
    *stream         = NULL;
155
156
    /* The file_io_handle, io_handle and stream_descriptor references are freed elsewhere
157
     */
158
0
    memory_free(
159
0
     internal_stream );
160
0
  }
161
0
  return( 1 );
162
0
}
163
164
/* Retrieves the type
165
 * Returns 1 if successful or -1 on error
166
 */
167
int libmdmp_stream_get_type(
168
     libmdmp_stream_t *stream,
169
     uint32_t *type,
170
     libcerror_error_t **error )
171
0
{
172
0
  libmdmp_internal_stream_t *internal_stream = NULL;
173
0
  static char *function                      = "libmdmp_stream_get_type";
174
175
0
  if( stream == NULL )
176
0
  {
177
0
    libcerror_error_set(
178
0
     error,
179
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
180
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
181
0
     "%s: invalid stream.",
182
0
     function );
183
184
0
    return( -1 );
185
0
  }
186
0
  internal_stream = (libmdmp_internal_stream_t *) stream;
187
188
0
  if( internal_stream->stream_descriptor == NULL )
189
0
  {
190
0
    libcerror_error_set(
191
0
     error,
192
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
193
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
194
0
     "%s: invalid internal stream - missing stream descriptor.",
195
0
     function );
196
197
0
    return( -1 );
198
0
  }
199
0
  if( type == NULL )
200
0
  {
201
0
    libcerror_error_set(
202
0
     error,
203
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
204
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
205
0
     "%s: invalid type.",
206
0
     function );
207
208
0
    return( -1 );
209
0
  }
210
0
  *type = internal_stream->stream_descriptor->type;
211
212
0
  return( 1 );
213
0
}
214
215
/* Reads data at the current offset into a buffer
216
 * Returns the number of bytes read or -1 on error
217
 */
218
ssize_t libmdmp_stream_read_buffer(
219
         libmdmp_stream_t *stream,
220
         void *buffer,
221
         size_t buffer_size,
222
         libcerror_error_t **error )
223
0
{
224
0
  libmdmp_internal_stream_t *internal_stream = NULL;
225
0
  static char *function                      = "libmdmp_stream_read_buffer";
226
0
  ssize_t read_count                         = 0;
227
228
0
  if( stream == NULL )
229
0
  {
230
0
    libcerror_error_set(
231
0
     error,
232
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
233
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
234
0
     "%s: invalid stream.",
235
0
     function );
236
237
0
    return( -1 );
238
0
  }
239
0
  internal_stream = (libmdmp_internal_stream_t *) stream;
240
241
0
  if( internal_stream->stream_descriptor == NULL )
242
0
  {
243
0
    libcerror_error_set(
244
0
     error,
245
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
246
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
247
0
     "%s: invalid stream - missing stream descriptor.",
248
0
     function );
249
250
0
    return( -1 );
251
0
  }
252
0
  read_count = libfdata_stream_read_buffer(
253
0
                internal_stream->stream_descriptor->data_stream,
254
0
                (intptr_t *) internal_stream->file_io_handle,
255
0
                buffer,
256
0
                buffer_size,
257
0
                0,
258
0
                error );
259
260
0
  if( read_count == -1 )
261
0
  {
262
0
    libcerror_error_set(
263
0
     error,
264
0
     LIBCERROR_ERROR_DOMAIN_IO,
265
0
     LIBCERROR_IO_ERROR_READ_FAILED,
266
0
     "%s: unable to read buffer from stream data stream.",
267
0
     function );
268
269
0
    return( -1 );
270
0
  }
271
0
  return( read_count );
272
0
}
273
274
/* Reads data at a specific offset into a buffer
275
 * Returns the number of bytes read or -1 on error
276
 */
277
ssize_t libmdmp_stream_read_buffer_at_offset(
278
         libmdmp_stream_t *stream,
279
         void *buffer,
280
         size_t buffer_size,
281
         off64_t offset,
282
         libcerror_error_t **error )
283
0
{
284
0
  static char *function = "libmdmp_stream_read_buffer_at_offset";
285
0
  ssize_t read_count    = 0;
286
287
0
  if( libmdmp_stream_seek_offset(
288
0
       stream,
289
0
       offset,
290
0
       SEEK_SET,
291
0
       error ) == -1 )
292
0
  {
293
0
    libcerror_error_set(
294
0
     error,
295
0
     LIBCERROR_ERROR_DOMAIN_IO,
296
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
297
0
     "%s: unable to seek offset.",
298
0
     function );
299
300
0
    return( -1 );
301
0
  }
302
0
  read_count = libmdmp_stream_read_buffer(
303
0
                stream,
304
0
                buffer,
305
0
                buffer_size,
306
0
                error );
307
308
0
  if( read_count < 0 )
309
0
  {
310
0
    libcerror_error_set(
311
0
     error,
312
0
     LIBCERROR_ERROR_DOMAIN_IO,
313
0
     LIBCERROR_IO_ERROR_READ_FAILED,
314
0
     "%s: unable to read buffer.",
315
0
     function );
316
317
0
    return( -1 );
318
0
  }
319
0
  return( read_count );
320
0
}
321
322
/* Seeks a certain offset of the data
323
 * Returns the offset if seek is successful or -1 on error
324
 */
325
off64_t libmdmp_stream_seek_offset(
326
         libmdmp_stream_t *stream,
327
         off64_t offset,
328
         int whence,
329
         libcerror_error_t **error )
330
0
{
331
0
  libmdmp_internal_stream_t *internal_stream = NULL;
332
0
  static char *function                      = "libmdmp_stream_seek_offset";
333
334
0
  if( stream == NULL )
335
0
  {
336
0
    libcerror_error_set(
337
0
     error,
338
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
339
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
340
0
     "%s: invalid stream.",
341
0
     function );
342
343
0
    return( -1 );
344
0
  }
345
0
  internal_stream = (libmdmp_internal_stream_t *) stream;
346
347
0
  if( internal_stream->stream_descriptor == NULL )
348
0
  {
349
0
    libcerror_error_set(
350
0
     error,
351
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
352
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
353
0
     "%s: invalid stream - missing stream descriptor.",
354
0
     function );
355
356
0
    return( -1 );
357
0
  }
358
0
  offset = libfdata_stream_seek_offset(
359
0
            internal_stream->stream_descriptor->data_stream,
360
0
            offset,
361
0
            whence,
362
0
            error );
363
364
0
  if( offset == -1 )
365
0
  {
366
0
    libcerror_error_set(
367
0
     error,
368
0
     LIBCERROR_ERROR_DOMAIN_IO,
369
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
370
0
     "%s: unable to seek in stream data stream.",
371
0
     function );
372
373
0
    return( -1 );
374
0
  }
375
0
  return( offset );
376
0
}
377
378
/* Retrieves the (current) offset
379
 * Returns 1 if successful or -1 on error
380
 */
381
int libmdmp_stream_get_offset(
382
     libmdmp_stream_t *stream,
383
     off64_t *offset,
384
     libcerror_error_t **error )
385
0
{
386
0
  libmdmp_internal_stream_t *internal_stream = NULL;
387
0
  static char *function                      = "libmdmp_stream_get_offset";
388
389
0
  if( stream == NULL )
390
0
  {
391
0
    libcerror_error_set(
392
0
     error,
393
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
394
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
395
0
     "%s: invalid stream.",
396
0
     function );
397
398
0
    return( -1 );
399
0
  }
400
0
  internal_stream = (libmdmp_internal_stream_t *) stream;
401
402
0
  if( internal_stream->stream_descriptor == NULL )
403
0
  {
404
0
    libcerror_error_set(
405
0
     error,
406
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
407
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
408
0
     "%s: invalid stream - missing stream descriptor.",
409
0
     function );
410
411
0
    return( -1 );
412
0
  }
413
0
  if( libfdata_stream_get_offset(
414
0
       internal_stream->stream_descriptor->data_stream,
415
0
       offset,
416
0
       error ) != 1 )
417
0
  {
418
0
    libcerror_error_set(
419
0
     error,
420
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
421
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
422
0
     "%s: unable to retrieve stream data stream offset.",
423
0
     function );
424
425
0
    return( -1 );
426
0
  }
427
0
  return( 1 );
428
0
}
429
430
/* Retrieves the size
431
 * Returns 1 if successful or -1 on error
432
 */
433
int libmdmp_stream_get_size(
434
     libmdmp_stream_t *stream,
435
     size64_t *size,
436
     libcerror_error_t **error )
437
0
{
438
0
  libmdmp_internal_stream_t *internal_stream = NULL;
439
0
  static char *function                      = "libmdmp_stream_get_size";
440
441
0
  if( stream == NULL )
442
0
  {
443
0
    libcerror_error_set(
444
0
     error,
445
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
446
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
447
0
     "%s: invalid stream.",
448
0
     function );
449
450
0
    return( -1 );
451
0
  }
452
0
  internal_stream = (libmdmp_internal_stream_t *) stream;
453
454
0
  if( internal_stream->stream_descriptor == NULL )
455
0
  {
456
0
    libcerror_error_set(
457
0
     error,
458
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
459
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
460
0
     "%s: invalid stream - missing stream descriptor.",
461
0
     function );
462
463
0
    return( -1 );
464
0
  }
465
0
  if( libfdata_stream_get_size(
466
0
       internal_stream->stream_descriptor->data_stream,
467
0
       size,
468
0
       error ) != 1 )
469
0
  {
470
0
    libcerror_error_set(
471
0
     error,
472
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
473
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
474
0
     "%s: unable to retrieve stream data stream size.",
475
0
     function );
476
477
0
    return( -1 );
478
0
  }
479
0
  return( 1 );
480
0
}
481
482
/* Retrieves the start offset
483
 * Returns 1 if successful or -1 on error
484
 */
485
int libmdmp_stream_get_start_offset(
486
     libmdmp_stream_t *stream,
487
     off64_t *start_offset,
488
     libcerror_error_t **error )
489
0
{
490
0
  libmdmp_internal_stream_t *internal_stream = NULL;
491
0
  static char *function                      = "libmdmp_stream_get_start_offset";
492
0
  size64_t segment_size                      = 0;
493
0
  uint32_t segment_flags                     = 0;
494
0
  int segment_file_index                     = 0;
495
496
0
  if( stream == NULL )
497
0
  {
498
0
    libcerror_error_set(
499
0
     error,
500
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
501
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
502
0
     "%s: invalid stream.",
503
0
     function );
504
505
0
    return( -1 );
506
0
  }
507
0
  internal_stream = (libmdmp_internal_stream_t *) stream;
508
509
0
  if( internal_stream->stream_descriptor == NULL )
510
0
  {
511
0
    libcerror_error_set(
512
0
     error,
513
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
514
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
515
0
     "%s: invalid internal stream - missing stream descriptor.",
516
0
     function );
517
518
0
    return( -1 );
519
0
  }
520
0
  if( libfdata_stream_get_segment_by_index(
521
0
       internal_stream->stream_descriptor->data_stream,
522
0
       0,
523
0
       &segment_file_index,
524
0
       start_offset,
525
0
       &segment_size,
526
0
       &segment_flags,
527
0
       error ) != 1 )
528
0
  {
529
0
    libcerror_error_set(
530
0
     error,
531
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
532
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
533
0
     "%s: unable to retrieve stream data stream segment: 0.",
534
0
     function );
535
536
0
    return( -1 );
537
0
  }
538
0
  return( 1 );
539
0
}
540
541
/* Retrieves the stream data file IO handle
542
 * Returns 1 if successful -1 on error
543
 */
544
int libmdmp_stream_get_data_file_io_handle(
545
     libmdmp_stream_t *stream,
546
     libbfio_handle_t **file_io_handle,
547
     libcerror_error_t **error )
548
0
{
549
0
  libmdmp_stream_io_handle_t *io_handle = NULL;
550
0
  static char *function                 = "libmdmp_stream_get_data_file_io_handle";
551
552
0
  if( libmdmp_stream_io_handle_initialize(
553
0
       &io_handle,
554
0
       stream,
555
0
       error ) != 1 )
556
0
  {
557
0
    libcerror_error_set(
558
0
     error,
559
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
560
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
561
0
     "%s: unable to create stream file IO handle.",
562
0
     function );
563
564
0
    goto on_error;
565
0
  }
566
0
  if( libbfio_handle_initialize(
567
0
       file_io_handle,
568
0
       (intptr_t *) io_handle,
569
0
       (int (*)(intptr_t **, libcerror_error_t **)) libmdmp_stream_io_handle_free,
570
0
       (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) libmdmp_stream_io_handle_clone,
571
0
       (int (*)(intptr_t *, int flags, libcerror_error_t **)) libmdmp_stream_io_handle_open,
572
0
       (int (*)(intptr_t *, libcerror_error_t **)) libmdmp_stream_io_handle_close,
573
0
       (ssize_t (*)(intptr_t *, uint8_t *, size_t, libcerror_error_t **)) libmdmp_stream_io_handle_read,
574
0
       (ssize_t (*)(intptr_t *, const uint8_t *, size_t, libcerror_error_t **)) libmdmp_stream_io_handle_write,
575
0
       (off64_t (*)(intptr_t *, off64_t, int, libcerror_error_t **)) libmdmp_stream_io_handle_seek_offset,
576
0
       (int (*)(intptr_t *, libcerror_error_t **)) libmdmp_stream_io_handle_exists,
577
0
       (int (*)(intptr_t *, libcerror_error_t **)) libmdmp_stream_io_handle_is_open,
578
0
       (int (*)(intptr_t *, size64_t *, libcerror_error_t **)) libmdmp_stream_io_handle_get_size,
579
0
       LIBBFIO_FLAG_IO_HANDLE_MANAGED | LIBBFIO_FLAG_IO_HANDLE_CLONE_BY_FUNCTION,
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_INITIALIZE_FAILED,
586
0
     "%s: unable to create file IO handle.",
587
0
     function );
588
589
0
    goto on_error;
590
0
  }
591
0
  return( 1 );
592
593
0
on_error:
594
0
  if( io_handle != NULL )
595
0
  {
596
0
    libmdmp_stream_io_handle_free(
597
0
     &io_handle,
598
0
     NULL );
599
0
  }
600
0
  return( -1 );
601
0
}
602