Coverage Report

Created: 2024-02-25 07:20

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