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