Coverage Report

Created: 2026-04-04 07:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmodi/libmodi/libmodi_bands_data_handle.c
Line
Count
Source
1
/*
2
 * The bands data handle functions
3
 *
4
 * Copyright (C) 2010-2025, 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 "libmodi_bands_data_handle.h"
27
#include "libmodi_data_block.h"
28
#include "libmodi_definitions.h"
29
#include "libmodi_io_handle.h"
30
#include "libmodi_libbfio.h"
31
#include "libmodi_libcerror.h"
32
#include "libmodi_libcnotify.h"
33
#include "libmodi_libfdata.h"
34
#include "libmodi_libfcache.h"
35
#include "libmodi_unused.h"
36
37
/* Creates bands data handle
38
 * Make sure the value data_handle is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libmodi_bands_data_handle_initialize(
42
     libmodi_bands_data_handle_t **data_handle,
43
     libmodi_io_handle_t *io_handle,
44
     libcerror_error_t **error )
45
111
{
46
111
  static char *function = "libmodi_bands_data_handle_initialize";
47
48
111
  if( data_handle == NULL )
49
0
  {
50
0
    libcerror_error_set(
51
0
     error,
52
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
53
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
54
0
     "%s: invalid data handle.",
55
0
     function );
56
57
0
    return( -1 );
58
0
  }
59
111
  if( *data_handle != NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
64
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
65
0
     "%s: invalid data handle value already set.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
111
  if( io_handle == NULL )
71
0
  {
72
0
    libcerror_error_set(
73
0
     error,
74
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
75
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
76
0
     "%s: invalid IO handle.",
77
0
     function );
78
79
0
    return( -1 );
80
0
  }
81
111
  *data_handle = memory_allocate_structure(
82
111
                  libmodi_bands_data_handle_t );
83
84
111
  if( *data_handle == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
89
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
90
0
     "%s: unable to create data handle.",
91
0
     function );
92
93
0
    goto on_error;
94
0
  }
95
111
  if( memory_set(
96
111
       *data_handle,
97
111
       0,
98
111
       sizeof( libmodi_bands_data_handle_t ) ) == NULL )
99
0
  {
100
0
    libcerror_error_set(
101
0
     error,
102
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
103
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
104
0
     "%s: unable to clear data handle.",
105
0
     function );
106
107
0
    memory_free(
108
0
     *data_handle );
109
110
0
    *data_handle = NULL;
111
112
0
    return( -1 );
113
0
  }
114
111
  if( libfdata_vector_initialize(
115
111
       &( ( *data_handle )->bands_vector ),
116
111
       (size64_t) 512,
117
111
       (intptr_t *) io_handle,
118
111
       NULL,
119
111
       NULL,
120
111
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libmodi_data_block_read_vector_element_data,
121
111
       NULL,
122
111
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
123
111
       error ) != 1 )
124
0
  {
125
0
    libcerror_error_set(
126
0
     error,
127
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
128
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
129
0
     "%s: unable to create bands vector.",
130
0
     function );
131
132
0
    goto on_error;
133
0
  }
134
111
  if( libfcache_cache_initialize(
135
111
       &( ( *data_handle )->bands_cache ),
136
111
       LIBMODI_MAXIMUM_CACHE_ENTRIES_DATA_BANDS,
137
111
       error ) != 1 )
138
0
  {
139
0
    libcerror_error_set(
140
0
     error,
141
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
142
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
143
0
     "%s: unable to create bands cache.",
144
0
     function );
145
146
0
    goto on_error;
147
0
  }
148
111
  return( 1 );
149
150
0
on_error:
151
0
  if( *data_handle != NULL )
152
0
  {
153
0
    if( ( *data_handle )->bands_vector != NULL )
154
0
    {
155
0
      libfdata_vector_free(
156
0
       &( ( *data_handle )->bands_vector ),
157
0
       NULL );
158
0
    }
159
0
    memory_free(
160
0
     *data_handle );
161
162
0
    *data_handle = NULL;
163
0
  }
164
0
  return( -1 );
165
111
}
166
167
/* Frees a data handle
168
 * Returns 1 if successful or -1 on error
169
 */
170
int libmodi_bands_data_handle_free(
171
     libmodi_bands_data_handle_t **data_handle,
172
     libcerror_error_t **error )
173
111
{
174
111
  static char *function = "libmodi_bands_data_handle_free";
175
111
  int result            = 1;
176
177
111
  if( data_handle == NULL )
178
0
  {
179
0
    libcerror_error_set(
180
0
     error,
181
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
182
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
183
0
     "%s: invalid data handle.",
184
0
     function );
185
186
0
    return( -1 );
187
0
  }
188
111
  if( *data_handle != NULL )
189
111
  {
190
111
    if( libfcache_cache_free(
191
111
         &( ( *data_handle )->bands_cache ),
192
111
         error ) != 1 )
193
0
    {
194
0
      libcerror_error_set(
195
0
       error,
196
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
197
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
198
0
       "%s: unable to free bands cache.",
199
0
       function );
200
201
0
      result = -1;
202
0
    }
203
111
    if( libfdata_vector_free(
204
111
         &( ( *data_handle )->bands_vector ),
205
111
         error ) != 1 )
206
0
    {
207
0
      libcerror_error_set(
208
0
       error,
209
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
210
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
211
0
       "%s: unable to free bands vector.",
212
0
       function );
213
214
0
      result = -1;
215
0
    }
216
111
    memory_free(
217
111
     *data_handle );
218
219
111
    *data_handle = NULL;
220
111
  }
221
111
  return( result );
222
111
}
223
224
/* Appends a segment
225
 * Returns 1 if successful or -1 on error
226
 */
227
int libmodi_bands_data_handle_append_segment(
228
     libmodi_bands_data_handle_t *data_handle,
229
     int segment_file_index,
230
     off64_t segment_offset,
231
     size64_t segment_size,
232
     uint32_t segment_flags,
233
     libcerror_error_t **error )
234
3.06k
{
235
3.06k
  static char *function = "libmodi_bands_data_handle_append_segment";
236
3.06k
  int segment_index     = 0;
237
238
3.06k
  if( data_handle == NULL )
239
0
  {
240
0
    libcerror_error_set(
241
0
     error,
242
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
243
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
244
0
     "%s: invalid data handle.",
245
0
     function );
246
247
0
    return( -1 );
248
0
  }
249
3.06k
  if( libfdata_vector_append_segment(
250
3.06k
       data_handle->bands_vector,
251
3.06k
       &segment_index,
252
3.06k
       segment_file_index,
253
3.06k
       segment_offset,
254
3.06k
       segment_size,
255
3.06k
       segment_flags,
256
3.06k
       error ) != 1 )
257
0
  {
258
0
    libcerror_error_set(
259
0
     error,
260
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
261
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
262
0
     "%s: unable to append segment to bands vector.",
263
0
     function );
264
265
0
    return( -1 );
266
0
  }
267
3.06k
  return( 1 );
268
3.06k
}
269
270
/* Reads data from the current offset into a compressed
271
 * Callback for the data stream
272
 * Returns the number of bytes read or -1 on error
273
 */
274
ssize_t libmodi_bands_data_handle_read_segment_data(
275
         libmodi_bands_data_handle_t *data_handle,
276
         libbfio_handle_t *file_io_handle,
277
         int segment_index,
278
         int segment_file_index LIBMODI_ATTRIBUTE_UNUSED,
279
         uint8_t *segment_data,
280
         size_t segment_data_size,
281
         uint32_t segment_flags LIBMODI_ATTRIBUTE_UNUSED,
282
         uint8_t read_flags LIBMODI_ATTRIBUTE_UNUSED,
283
         libcerror_error_t **error )
284
0
{
285
0
  libmodi_data_block_t *data_block = NULL;
286
0
  static char *function            = "libmodi_bands_data_handle_read_segment_data";
287
0
  size_t read_size                 = 0;
288
0
  size_t segment_data_offset       = 0;
289
0
  off64_t element_data_offset      = 0;
290
291
0
  LIBMODI_UNREFERENCED_PARAMETER( segment_file_index )
292
0
  LIBMODI_UNREFERENCED_PARAMETER( segment_flags )
293
0
  LIBMODI_UNREFERENCED_PARAMETER( read_flags )
294
295
0
  if( data_handle == NULL )
296
0
  {
297
0
    libcerror_error_set(
298
0
     error,
299
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
300
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
301
0
     "%s: invalid data handle.",
302
0
     function );
303
304
0
    return( -1 );
305
0
  }
306
0
  if( data_handle->current_offset < 0 )
307
0
  {
308
0
    libcerror_error_set(
309
0
     error,
310
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
311
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
312
0
     "%s: invalid data handle - current offset value out of bounds.",
313
0
     function );
314
315
0
    return( -1 );
316
0
  }
317
0
  if( segment_index < 0 )
318
0
  {
319
0
    libcerror_error_set(
320
0
     error,
321
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
322
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
323
0
     "%s: invalid segment index value out of bounds.",
324
0
     function );
325
326
0
    return( -1 );
327
0
  }
328
0
  if( segment_data == NULL )
329
0
  {
330
0
    libcerror_error_set(
331
0
     error,
332
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
333
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
334
0
     "%s: invalid segment data.",
335
0
     function );
336
337
0
    return( -1 );
338
0
  }
339
0
  if( segment_data_size > (size_t) SSIZE_MAX )
340
0
  {
341
0
    libcerror_error_set(
342
0
     error,
343
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
344
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
345
0
     "%s: invalid segment data size value exceeds maximum.",
346
0
     function );
347
348
0
    return( -1 );
349
0
  }
350
0
  if( data_handle->data_size == 0 )
351
0
  {
352
0
    if( libfdata_vector_get_size(
353
0
         data_handle->bands_vector,
354
0
         &( data_handle->data_size ),
355
0
         error ) != 1 )
356
0
    {
357
0
      libcerror_error_set(
358
0
       error,
359
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
360
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
361
0
       "%s: unable to retrieve size of bands vector.",
362
0
       function );
363
364
0
      return( -1 );
365
0
    }
366
0
  }
367
0
  if( (size64_t) data_handle->current_offset >= data_handle->data_size )
368
0
  {
369
0
    return( 0 );
370
0
  }
371
0
  while( segment_data_size > 0 )
372
0
  {
373
0
    if( libfdata_vector_get_element_value_at_offset(
374
0
         data_handle->bands_vector,
375
0
         (intptr_t *) file_io_handle,
376
0
         (libfdata_cache_t *) data_handle->bands_cache,
377
0
         data_handle->current_offset,
378
0
         &element_data_offset,
379
0
         (intptr_t **) &data_block,
380
0
         0,
381
0
         error ) != 1 )
382
0
    {
383
0
      libcerror_error_set(
384
0
       error,
385
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
386
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
387
0
       "%s: unable to retrieve data block at offset: %" PRIi64 " (0x%08" PRIx64 ").",
388
0
       function,
389
0
       data_handle->current_offset,
390
0
       data_handle->current_offset );
391
392
0
      return( -1 );
393
0
    }
394
0
    if( data_block == NULL )
395
0
    {
396
0
      libcerror_error_set(
397
0
       error,
398
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
399
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
400
0
       "%s: invalid data block.",
401
0
       function );
402
403
0
      return( -1 );
404
0
    }
405
0
    if( data_block->data == NULL )
406
0
    {
407
0
      libcerror_error_set(
408
0
       error,
409
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
410
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
411
0
       "%s: invalid data block - missing data.",
412
0
       function );
413
414
0
      return( -1 );
415
0
    }
416
0
    if( ( element_data_offset < 0 )
417
0
     || ( (size64_t) element_data_offset >= data_block->data_size ) )
418
0
    {
419
0
      libcerror_error_set(
420
0
       error,
421
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
422
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
423
0
       "%s: invalid element data offset value out of bounds.",
424
0
       function );
425
426
0
      return( -1 );
427
0
    }
428
0
    read_size = data_block->data_size - element_data_offset;
429
430
0
    if( read_size > segment_data_size )
431
0
    {
432
0
      read_size = segment_data_size;
433
0
    }
434
0
    if( memory_copy(
435
0
         &( segment_data[ segment_data_offset ] ),
436
0
         &( ( data_block->data )[ element_data_offset ] ),
437
0
         read_size ) == NULL )
438
0
    {
439
0
      libcerror_error_set(
440
0
       error,
441
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
442
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
443
0
       "%s: unable to copy block data.",
444
0
       function );
445
446
0
      return( -1 );
447
0
    }
448
0
    segment_data_offset += read_size;
449
0
    segment_data_size   -= read_size;
450
451
0
    data_handle->current_offset += read_size;
452
453
0
    if( (size64_t) data_handle->current_offset >= data_handle->data_size )
454
0
    {
455
0
      break;
456
0
    }
457
0
  }
458
0
  return( (ssize_t) segment_data_offset );
459
0
}
460
461
/* Seeks a certain offset of the data
462
 * Callback for the data stream
463
 * Returns the offset if seek is successful or -1 on error
464
 */
465
off64_t libmodi_bands_data_handle_seek_segment_offset(
466
         libmodi_bands_data_handle_t *data_handle,
467
         intptr_t *file_io_handle LIBMODI_ATTRIBUTE_UNUSED,
468
         int segment_index,
469
         int segment_file_index LIBMODI_ATTRIBUTE_UNUSED,
470
         off64_t segment_offset,
471
         libcerror_error_t **error )
472
0
{
473
0
  static char *function = "libmodi_bands_data_handle_seek_segment_offset";
474
475
0
  LIBMODI_UNREFERENCED_PARAMETER( file_io_handle )
476
0
  LIBMODI_UNREFERENCED_PARAMETER( segment_file_index )
477
478
0
  if( data_handle == NULL )
479
0
  {
480
0
    libcerror_error_set(
481
0
     error,
482
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
483
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
484
0
     "%s: invalid data handle.",
485
0
     function );
486
487
0
    return( -1 );
488
0
  }
489
0
  if( segment_index != 0 )
490
0
  {
491
0
    libcerror_error_set(
492
0
     error,
493
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
494
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
495
0
     "%s: invalid segment index value out of bounds.",
496
0
     function );
497
498
0
    return( -1 );
499
0
  }
500
0
  if( segment_offset < 0 )
501
0
  {
502
0
    libcerror_error_set(
503
0
     error,
504
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
505
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
506
0
     "%s: invalid segment offset value out of bounds.",
507
0
     function );
508
509
0
    return( -1 );
510
0
  }
511
0
  data_handle->current_offset = segment_offset;
512
513
0
  return( segment_offset );
514
0
}
515